Rails 3: Как мне найти объект без детей? - PullRequest
1 голос
/ 15 августа 2011

У меня есть 3 модели

class Task < ActiveRecord::Base
  belongs_to :user, :dependent => :destroy
  has_many :clock_ins

  accepts_nested_attributes_for :clock_ins, :allow_destroy => true
end

class ClockIn < ActiveRecord::Base
  belongs_to :task, :dependent => :destroy
  has_one :clock_out
end

class ClockOut < ActiveRecord::Base
  belongs_to :clock_in, :dependent => :destroy
end

В настоящее время я могу создать ClockIn для каждого Task.

Когда я начинаю новый ClockIn, я хочу создатьClockOut для того, что в данный момент открыто Task.

Как найти в моих заданиях задачу с ClockIn, у которой нет ClockOut?


Решение

  • Объединить модели

  • Исправить уничтожает

  • Повторять все задачи, затем обновлять task.clocks.where(:clock_out => nil).first.update_attribute :clock_out, Time.now

1 Ответ

1 голос
/ 15 августа 2011

Поскольку между clock_in и clock_out имеется взаимно-однозначное отношение, переключение has_one и belongs_to не должно иметь большого значения.Какие данные хранятся в clock_in и clock_out?Если это просто дата и время, вы можете рассмотреть возможность объединения двух моделей и использования одной таблицы.Если вы не хотите менять какие-либо моделирование LEFT OUTER JOIN это путь.Таким образом, у вас есть три варианта:

  • Объединить модели:

    class Task < ActiveRecord::Base
      belongs_to :user
      has_many :working_hours
    
      accepts_nested_attributes_for :working_hours, :allow_destroy => true
    end
    
    class WorkingHour < ActiveRecord::Base
      belongs_to :task
    
      # has two columns clock_in_time and clock_out_time
    end
    
    task.working_hours.where(:clock_out_time => nil).first.update_attribute(:clock_out_time => Time.now)
    
  • Переключатель has_one и принадлежат_to

    class ClockIn < ActiveRecord::Base
      belongs_to :task
      belongs_to :clock_out
      # now clock_ins will have column check_out_id
    end
    
    class ClockOut < ActiveRecord::Base
      has_one :clock_in
      # doen't have any check_in_id
    end
    
    task.clock_ins.where(:clock_out_id => nil).first.create_clock_out(:time => Time.now)
    
  • Переходите к внешнему соединению

    class ClockIn < ActiveRecord::Base
      belongs_to :task
      has_one :clock_out
    
      scope :has_no_check_out, {
        :joins => "LEFT OUTER JOIN clock_outs ON clock_ins.id = clock_outs.clock_in_id"
        :conditions => "clock_outs.clock_in_id IS NULL"
      }
    end
    
    task.clock_ins.has_no_check_out.first.create_clock_out(:time => Time.now)
    

Обратите внимание, что ваши :dependent => :destroy определения выглядят не очень хорошо.В настоящее время, если вы уничтожите clock_out, соответствующий clock_in будет уничтожен, в результате чего соответствующая задача будет уничтожена, а другие clock_ins будут связаны с этой задачей.Также, когда задача будет уничтожена, это приведет к уничтожению пользователя.Это кажется очень странной цепочкой событий.Уничтожение clock_out приводит к уничтожению пользователя, Ой!

Вы должны использовать :dependent => :destroy, как показано ниже:

# user.rb
has_many :tasks, :dependent => :destroy

# task.rb
has_many :clock_ins, :dependent => :destroy

# clock_in.rb
has_one :clock_out, :dependent => :destroy
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...