【问题标题】:Rails 3: How can I find an object with no children in itRails 3:我怎样才能找到一个没有孩子的对象
【发布时间】:2011-08-14 21:03:48
【问题描述】:

我有 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

目前我可以为每个Task 创建一个ClockIn

当我开始一个新的ClockIn 时,我想为当前打开的Task 创建一个ClockOut

如何在我的任务中搜索具有ClockIn 而没有ClockOut 的任务?


解决方案

  • 组合模型

  • 修复破坏

  • 迭代所有任务然后更新task.clocks.where(:clock_out =&gt; nil).first.update_attribute :clock_out, Time.now

【问题讨论】:

标签: ruby-on-rails-3 activerecord model controller


【解决方案1】:

由于您在clock_in 和clock_out 之间存在一对一的关系,因此切换has_onebelongs_to 应该没有太大区别。 clock_in 和clock_out 中存储的数据是什么?如果 is 只是一个日期时间,您可能需要考虑合并两个模型并使用单个表。如果你不想改变任何造型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 和 belongs_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 =&gt; :destroy 定义看起来不太好。目前如果你销毁一个clock_out,对应的clock_in会被销毁,导致对应的task被销毁,而其他与task相关的clock_in被孤立。同样,当任务被销毁时,也会导致用户被销毁。这似乎是一个非常奇怪的事件链。销毁clock_out会导致销毁用户,哎哟!

您应该使用:dependent =&gt; :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

【讨论】:

  • 现在修复破坏。打算尝试更改模型,一旦我得到它的工作,我会标记答案。谢谢!
  • 由于最后一次打卡可能是在另一个任务中,所以查询可能不太准确。
  • 我最终使用了 task.clocks.where(:clock_out => nil).first.update_attribute :clock_out, Time.now
猜你喜欢
  • 2017-09-26
  • 2018-05-27
  • 1970-01-01
  • 1970-01-01
  • 2020-10-29
  • 1970-01-01
  • 2014-12-04
  • 2017-06-12
  • 1970-01-01
相关资源
最近更新 更多