views:

36

answers:

1

Here's some of my production code (I had to force line breaks):

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)

Yes, I'm trying to find or create a unique ActiveRecord::Base object. But in current form it's very ugly. Instead, I'd like to use something like this:

task = Task.SOME_METHOD :username => username, :timestamp => timestamp ...

I know about find_by_something key=>value, but it's not an option here. I need all values to be unique. Is there a method that'll do the same as find_or_create_by, but take a hash as an input? Or something else with similat semantics?

+3  A: 

No, but it's pretty easy to write something that does the same thing.

In Rails 2.1 - 2.3:

Task.first(:conditions => attributes) || Task.create(attributes)

In Rails 3:

Task.where(attributes).first || Task.create(attributes)

You can always write a method called find_or_create to encapsulate this if you'd like. Definitely done it myself in the past:

class Task
  def self.find_or_create(attributes)
    # add one of the implementations above
  end
end

From the OP: Sad that there is nothing more easy. So I added a helper method directly into ActiveRecord::Base:

class ActiveRecord::Base                 
  def self.find_or_create(attributes)    
    self.first(:conditions => attributes) || self.create(attributes)
  end                                                                     
end
wuputah
Yea, you can certainly add it to AR::Base, but I find there is some model-specific behavior, like you may want to chose specific unique columns to do the find. But you can always override it, too.
wuputah