0

我有以下模型/关联设置:

class Contact < ActiveRecord::Base
  has_and_belongs_to_many :assigned_users, class_name: 'User'

  def auto_assign_team_member(project)
    team = project.teams(true).order('last_assigned_contact_at ASC').first
    if team && (user = team.user)
      self.assigned_users << user
      team.update_attribute(:last_assigned_contact_at, Time.now)
    end
  end
end

class Team < ActiveRecord::Base
  belongs_to :user
  belongs_to :project
end

class User < ActiveRecord::Base
  has_many :teams
  has_many :projects, through: :teams
  has_and_belongs_to_many :assigned_contacts, class_name: 'Contact'
end

class Project < ActiveRecord::Base
  has_many :teams
  has_many :users, through: :teams
end

我还有一组Contact实例,我遍历并执行该auto_assign_team_member方法。我的问题是lvar几乎每次执行都会team返回同一个团队。我在表中有两条记录,我的目的是将团队成员平均分配到关联中。teamsContact#assigned_users

在控制台中,它可以工作:

project.teams(true).order('last_assigned_contact_at ASC').first #=> Team(user_id: 1)
project.teams(true).order('last_assigned_contact_at ASC').first.update_attribute(:last_assigned_contact_at, Time.now)
project.teams(true).order('last_assigned_contact_at ASC').first #=> Team(user_id: 2)

知道我在哪里出错了吗?

编辑如果有人感兴趣,我已经创建了一个小应用程序来重现这个https://github.com/injekt/teamr

您可以简单rake db:seed地运行运行测试数据,输出应该均匀分布在每个用户上,而不是每次都显示同一个用户。

编辑事实证明,这样做update_attribute(:last_assigned_contact_at, 'now()')效果很好。所以也许 Rails 正在做一些时髦的事情?我意识到这需要高精度,但我认为 Rails 可以处理

4

1 回答 1

2

似乎问题在于 Rails 从任何 Time 对象中舍入 usec,可能是因为只有 PostgreSQL 真正支持这种精度,它们是“没有时区的时间戳”数据类型。

时间戳属性与其他属性的处理方式不同,此模块为它们定义了一个自定义设置器:https ://github.com/rails/rails/blob/3-2-stable/activerecord/lib/active_record/attribute_methods/time_zone_conversion.rb

在比较和分配值之前,时间对象会被四舍五入https://github.com/rails/rails/blob/3-2-stable/activerecord/lib/active_record/attribute_methods/time_zone_conversion.rb#L46

奇怪的问题是,对于内置的 Rails 时间戳列,精度是存在的。这是因为内置的时间戳通过调用绕过了自定义设置器write_attribute(:column, value),它完全插入了整个时间值以及任何 usec。

所以解决方法是这样做而不是team.update_attribute调用

team.send(:write_attribute, :last_assigned_contact_at, Time.current)
team.save

这有效地绕过了整个自定义设置器逻辑并像处理内置时间戳更新一样处理值。

于 2012-12-18T15:43:10.417 回答