0

我想简化这个复杂的逻辑来创建唯一的 Track 对象。

def self.create_unique(p)
  f = Track.find :first, :conditions => ['user_id = ? AND target_id = ? AND target_type = ?', p[:user_id], p[:target_id], p[:target_type]]
  x = ((p[:target_type] == 'User') and (p[:user_id] == p[:target_id]))
  Track.create(p) if (!f and !x)
end
4

2 回答 2

2

这是用一些简单的提取方法重写的:

def self.create_unique(attributes)
  return if exists_for_user_and_target?(attributes)
  return if user_is_target?(attributes)

  create(attributes)
end

def self.exists_for_user_and_target?(attributes)
  exists?(attributes.slice(:user_id, :target_id, :target_type))
end

def self.user_is_target?(attributes)
  attributes[:target_type] == 'User' && attributes[:user_id] == attributes[:target_id]
end

这次重写显示了我对帮助解释意图的小型描述性方法的偏好。我也喜欢在像这样的情况下使用保护子句create_unique;最后一行 ( ) 揭示了幸福的道路create(attributes),但守卫清楚地描述了例外情况。我相信我使用exists?inexists_for_user_and_target?可以很好地替代find :first,尽管它假设 Rails 3。

您也可以考虑使用唯一性主动模型验证。

于 2012-10-07T02:46:26.803 回答
-1
@@keys = [:user_id, :target_id, :target_type]
def self.create_unique(p)
  return if Track.find :first, :conditions => [
    @@keys.map{|k| "#{k} = ?"}.join(" and "),
    *@@keys.map{|k| p[k]}
  ]
  return if p[@@keys[0]] == p[@@keys[1]]
  return if p[@@keys[2]] == "User"
  Track.create(p)
end
于 2012-10-07T05:25:40.663 回答