这是我的一些生产代码(我不得不强制换行):
task = Task.find_or_create_by_username_and_timestamp_and_des \
cription_and_driver_spec_and_driver_spec_origin(username,tim \
estamp,description,driver_spec,driver_spec_origin)
是的,我正在尝试查找或创建一个唯一的ActiveRecord::Base
对象。但目前的形式非常难看。相反,我想使用这样的东西:
task = Task.SOME_METHOD :username => username, :timestamp => timestamp ...
我知道find_by_something key=>value
,但这不是一个选择。我需要所有的价值观都是独特的。是否有一种方法与find_or_create_by
相同,但是将哈希作为输入?或者使用similat语义的其他东西?
答案 0 :(得分:19)
Rails 3.2首先将first_or_create
引入ActiveRecord。它不仅具有所请求的功能,而且还适用于ActiveRecord关系的其余部分:
Task.where(attributes).first_or_create
在Rails 3.0和3.1中:
Task.where(attributes).first || Task.create(attributes)
在Rails 2.1 - 2.3中:
Task.first(:conditions => attributes) || Task.create(attributes)
在旧版本中,如果您愿意,可以随时编写一个名为find_or_create
的方法来封装它。绝对是我自己过去做过的:
class Task
def self.find_or_create(attributes)
# add one of the implementations above
end
end
答案 1 :(得分:4)
我还扩展了@ wuputah的方法来接受一个哈希数组,这在db/seeds.rb
class ActiveRecord::Base
def self.find_or_create(attributes)
if attributes.is_a?(Array)
attributes.each do |attr|
self.find_or_create(attr)
end
else
self.first(:conditions => attributes) || self.create(attributes)
end
end
end
# Example
Country.find_or_create({:name => 'Aland Islands', :iso_code => 'AX'})
# take array of hashes
Country.find_or_create([
{:name => 'Aland Islands', :iso_code => 'AX'},
{:name => 'Albania', :iso_code => 'AL'},
{:name => 'Algeria', :iso_code => 'DZ'}
])