Комплексные ассоциации для Rails - PullRequest
0 голосов
/ 07 декабря 2011

Застрял на этом, если бы вы могли взглянуть ..:)

Я хочу получить все незавершенные проекты, включая все незавершенные задачи для определенного пользователя.

Этомои настройки до сих пор:

User (devise)
    has_one :employee

Employee
    belongs_to :user
    has_and_belongs_to_many :tasks
    has_and_belongs_to_many :unfinished_tasks, :conditions => { :tasks => { :completed_at => nil } }, :class_name => "Task"
    has_many :unfinished_projects, :through => :unfinished_tasks, :source => :project, :uniq => true   ( :include => :unfinished_tasks OR :include => :tasks ? )

Project
    has_many :tasks

Task
    belongs_to :project
    has_and_belongs_to_many :employees

На мой взгляд (хам) Я хотел бы иметь что-то вроде этого:

- for project in current_user.employee.unfinished_projects

    = project.name

    # THESE ARE NOT THE ONLY THE TASKS FOR THE CURRENT_USER
    - for task in project.tasks    ( OR project.unfinished_tasks ? )

        = task.name

Эта настройка работает для проектов, есть толькопроекты, в которых есть незавершенные задачи.

Но я не уверен, как включить незавершенные задачи в эти проекты.

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

РЕДАКТИРОВАТЬ: Сложность в том, что задачи должны быть для current_user.Проекты загружаются идеально.

Но когда он загружает задачи:

- for task in project.tasks.unfinished

Это делает это:

Task Load (1.3ms)  SELECT `tasks`.* FROM `tasks` WHERE `tasks`.`project_id` IN (12, 7, 13, 15, 14, 10, 16, 17, 9, 2, 3)
Task Load (0.4ms)  SELECT `tasks`.* FROM `tasks` WHERE `tasks`.`project_id` = 12 AND `tasks`.`completed_at` IS NULL
Task Load (0.3ms)  SELECT `tasks`.* FROM `tasks` WHERE `tasks`.`project_id` = 7 AND `tasks`.`completed_at` IS NULL
Task Load (0.6ms)  SELECT `tasks`.* FROM `tasks` WHERE `tasks`.`project_id` = 13 AND `tasks`.`completed_at` IS NULL
etc.

Что нужно сделать, это получить задачисотрудник:

Employee
  Projects
    Tasks

Какими должны быть задачи, которые были внутренне объединены в запросе проектов.

Ответы [ 3 ]

0 голосов
/ 07 декабря 2011

Итак, ответ на мой вопрос таков:

Модели:

Employee:
  has_and_belongs_to_many :tasks
  has_many :projects, :through => :tasks, :uniq => true

Project:
  has_many :tasks
  scope :unfinished, :include => :tasks, :conditions => { :tasks => { :completed_at => nil } }

Task:
  scope :unfinished, :conditions => { :completed_at => nil }
  scope :of_user, lambda { |user| { :include => :employees, :conditions => { :employees => { :id => user.employee.id } } } }

Мнение:

- for project in current_user.employee.projects.unfinished

    - for task in project.tasks.unfinished.of_user( current_user )

Меня ОЧЕНЬ раздражает, что Project.unfinished уже содержит незавершенные задачи.

ПОЧЕМУ мне нужно получить их снова, дает мне новый запрос для каждого проекта! Должно быть ненужным верно?

0 голосов
/ 08 декабря 2011

Итак, повторив это снова, я не понял, в чем заключалась моя проблема. Теперь изменилось несколько вещей: я использую области действия, в том числе для быстрой загрузки, и нет области действия для самого project.tasks.

Модель проекта:

has_many :tasks
scope :assigned_to, lambda { |employee| { :include => { :tasks => :employees }, :conditions => { :tasks => { :employees => { :id => employee.id } } } } }
scope :unfinished, :include => :tasks, :conditions => { :tasks => { :completed_at => nil } }

Мнение:

- for project in Project.assigned_to( current_user.employee ).unfinished
  = project.name
  - for task in project.tasks
    = task.name

Дает мне этот хороший MySQL-запрос:

SELECT `projects`.`id` AS t0_r0, `projects`.`name` AS t0_r1, `projects`.`description` AS t0_r2, `projects`.`completed_at` AS t0_r3, `projects`.`created_at` AS t0_r4, `projects`.`updated_at` AS t0_r5, `tasks`.`id` AS t1_r0, `tasks`.`name` AS t1_r1, `tasks`.`description` AS t1_r2, `tasks`.`estimated_duration` AS t1_r3, `tasks`.`calculated_duration` AS t1_r4, `tasks`.`status` AS t1_r5, `tasks`.`completed_at` AS t1_r6, `tasks`.`project_id` AS t1_r7, `tasks`.`created_at` AS t1_r8, `tasks`.`updated_at` AS t1_r9, `employees`.`id` AS t2_r0, `employees`.`alias` AS t2_r1, `employees`.`comments` AS t2_r2, `employees`.`user_id` AS t2_r3, `employees`.`created_at` AS t2_r4, `employees`.`updated_at` AS t2_r5 FROM `projects` LEFT OUTER JOIN `tasks` ON `tasks`.`project_id` = `projects`.`id` LEFT OUTER JOIN `employees_tasks` ON `employees_tasks`.`task_id` = `tasks`.`id` LEFT OUTER JOIN `employees` ON `employees`.`id` = `employees_tasks`.`employee_id` WHERE `employees`.`id` = 3 AND `tasks`.`completed_at` IS NULL

Работает как шарм!

Особая благодарность Тарын ..;)

0 голосов
/ 07 декабря 2011

Предполагая, что мой вопрос (выше) является истинным примером того, что вы хотели бы видеть.

вы можете использовать named_scopes для этого.

Например:

Task
   named_scope :unfinished, :conditions => {:unfinished => true}

или любое другое условие, показывающее, что оно незакончено.Затем вы можете использовать:

 - for task in project.tasks.unfinished

named_scope для "unfinished_projects" похож, но немного сложнее.Он требует некоторого чистого SQL - который будет зависеть от используемой вами базы данных, но обычно требует, чтобы вы присоединились к задачам и обнаружили, что у проекта есть одна незавершенная задача.Я предполагаю, что это может приблизиться к тому, что вам нужно:

Project
   named_scope :unfinished, 
    :joins => 'inner join tasks on tasks.project_id = projects.id',
    :conditions => ['tasks.unfinished IS TRUE']

Затем вы будете использовать его, как указано выше:

  - for project in current_user.employee.projects.unfinished

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

Project
   named_scope :unfinished_for_user, lambda {|the_user_id|
    :joins => 'inner join tasks on tasks.project_id = projects.id',
    :conditions => ['tasks.unfinished IS TRUE AND tasks.user_id = ?', the_user_id]
   }
...