我想简化这个复杂的逻辑来创建独特的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
答案 0 :(得分: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?
中使用exists_for_user_and_target?
可能是find :first
的一个很好的替代品,尽管它假设Rails 3。
您也可以考虑使用唯一性主动模型验证。
答案 1 :(得分:-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