2010-10-01 6 views
9

Hier einige meines Produktionscode (ich musste Zeilenumbrüche erzwingen):Gibt es find_or_create_by_, die einen Hash in Rails nimmt?

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) 

Ja, ich versuche ein einzigartiges ActiveRecord::Base Objekt zu finden oder zu schaffen. Aber in der jetzigen Form ist es sehr hässlich. Stattdessen würde Ich mag so etwas verwenden:

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

Ich weiß über find_by_something key=>value, aber es ist nicht hier Option. Ich brauche alle Werte, um einzigartig zu sein. Gibt es eine Methode, die die gleichen wie find_or_create_by tun würde, aber einen Hash als Eingabe nehmen? Oder etwas anderes mit Ähnlichkeitssemantik?

Antwort

19

Rails 3.2 erste first_or_create zu Active eingeführt. Nicht nur, dass es die gewünschte Funktionalität, aber sie paßt auch in dem Rest der Active Beziehungen:

Task.where(attributes).first_or_create 

In Rails 3.0 und 3.1:

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

In Rails 2,1-2,3:

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

In den älteren Versionen konnte man immer eine Methode schreiben find_or_create nannte diese verkapseln, wenn Sie möchten. Auf jeden Fall es selbst getan in der Vergangenheit:

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

Ja, kann man sicherlich hinzufügen es zu AR :: Base, aber ich finde, es gibt einige modellspezifische Verhalten, wie Sie bestimmte spezifische Spalten für die Suche auswählen möchten. Aber Sie können es auch immer überschreiben. – wuputah

4

ich auch die @ wuputah-Verfahren erstrecken sich in einem Array von Hashes zu nehmen, was sehr nützlich ist, wenn verwendete innen 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'} 
]) 
Verwandte Themen