是否有在Rails中使用哈希的find_or_create_by_?

时间:2010-10-01 17:02:16

标签: ruby-on-rails activerecord

这是我的一些生产代码(我不得不强制换行):

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语义的其他东西?

2 个答案:

答案 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'}
])