我有以下模型/关联设置:
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
方法。我的问题是team
lvar每次执行都会为几乎返回相同的团队。我在teams
表中有两条记录,我的目的是将团队成员均匀地分配到Contact#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可以处理
答案 0 :(得分:2)
似乎问题是Rails从任何Time对象中舍入usec,可能是因为只有PostgreSQL实际上支持那种“没有时区的时间戳”数据类型的精度。
时间戳属性的处理方式与其他属性不同,此模块为其定义自定义设置器:https://github.com/rails/rails/blob/3-2-stable/activerecord/lib/active_record/attribute_methods/time_zone_conversion.rb
之前,时间对象会被舍入奇怪的问题是,对于内置的Rails时间戳列,精度就在那里。
这是因为内置时间戳通过调用write_attribute(:column, value)
来绕过自定义设置器,team.update_attribute
只是平坦地插入整个时间值,以及任何usec。
因此修复此问题而不是team.send(:write_attribute, :last_assigned_contact_at, Time.current)
team.save
调用
{{1}}
这有效地绕过了整个自定义setter逻辑并处理了值,就像处理内置时间戳更新一样。