2010-10-22 9 views
42

Chcę użyć find_or_create_by, ale to polecenie NIE działa. Nie "odnajduje" ani "tworzy" z innymi atrybutami.Jak mogę przekazać wiele atrybutów do find_or_create_by w Rails 3?

productproperty = ProductProperty.find_or_create_by_product_id(:product_id => product.id, :property_id => property.id, :value => d[descname]) 

Nie wydaje się być bardzo mało, lub nie, informacje o wykorzystaniu dynamicznych dystansu w szynach 3. „i” -ing to razem daje mi nieznany błąd metody.

UPDATE:

Początkowo nie mogłem uzyskać następujące do pracy. Załóżmy, że nie jestem idiotą, a "produkt" jest instancją modelu AR produktu.

product.product_properties.find_or_create_by_property_id_and_value(:property_id => 1, :value => "X") 

Metody błąd:

no such keys: property_id, value 

nie mogłem zrozumieć, że obecnie. Dopiero dziś rano znalazłem odniesienie do podania wartości takich jak ta:

product.product_properties.find_or_create_by_property_id_and_value(1, "X") 

I voila, działa dobrze. Spodziewałbym się, że hash zadziała w tej samej sytuacji, ale chyba nie.

Sądzę, że uzyskasz mniejszą liczbę głosów, jeśli coś przegapisz w Internecie?

+3

Przez "anding" masz na myśli coś podobnego do opisanego tutaj: [Rails find_or_create przez więcej niż jeden atrybut?] (Http://stackoverflow.com/questions/3046607/rails-find-lub-create-by-more- niż jeden atrybut)? – Matt

+0

Próbowałem tego i działa dobrze. Co dokładnie nie działa? Czy otrzymujesz błąd? Jaka jest wartość 'productproperty'? Dokumentacja jest dostępna tutaj: http://api.rubyonrails.org/classes/ActiveRecord/Base.html (w wyszukiwarce dynamicznych atrybutów) – Mischa

Odpowiedz

52

Jeśli chcesz wyszukiwać według wielu atrybutów, możesz użyć "i", aby je dodać. Na przykład:

productproperty = ProductProperty.find_or_create_by_product_id_and_property_id_and_value(:product_id => product.id, :property_id => property.id, :value => d[descname]) 

Jest jeden drobny haczyk być świadomi. Zawsze zwróci wskazany obiekt, nawet jeśli nie można go zapisać z powodu błędów sprawdzania poprawności. Sprawdź więc, czy zwracany obiekt ma identyfikator (czy jest nieprawidłowy?). Nie zakładaj jej w bazie danych.

Alternatywnie, można użyć „bang” wersję metody podnieść błąd, jeśli obiekt nie może być zapisane:

http://guides.rubyonrails.org/active_record_querying.html#find-or-create-by-bang

Odnosi się do szyn 3.

+2

Tak, to zmieniło się w Rails 4. Teraz tylko Ty potrzebujesz 'find_or_create_by' i dowolnych parametrów, które chcesz. Zobacz http://stackoverflow.com/questions/22520274/rails-4-find-or-create-by-method-doesnt-work –

23

Zobacz http://api.rubyonrails.org/classes/ActiveRecord/Base.html:

Z jednym parametrem zapytania:

productproperty = ProductProperty.find_or_create_by_product_id(product.id) { |u| u.property_id => property_id, u.value => d[descname] }) 

lub rozszerzony z wieloma parametrami:

productproperty = ProductProperty.find_or_create_by_product_id(:product_id => product.id, :property_id => property_id, :value => d[descname]) { |u| u.property_id => property_id, u.value => d[descname] }) 

będzie współpracować z:

conditions = { :product_id => product.id, 
       :property_id => property.id, 
       :value => d[descname] } 

pp = ProductProperty.find(:first, :conditions => conditions) || ProductProperty.create(conditions) 
+0

Przepraszam się pomyliłem, poprawiłem teraz. – Lichtamberg

+0

Ale to będzie wyszukiwanie tylko przez "product_id", a gdy found/created ustawi "property_id" i "value". Chyba @AKWF chce przeszukać wszystkie 3 wartości. – Matt

+0

Działa to również z wieloma parametrami ... Zaktualizowano mój wpis – Lichtamberg

9

ja już znalezione w Railsach 3.1 nie musisz przekazywać atrybutów jako hasha. Po prostu przekazujesz wartości same.

ProductProperty.find_or_create_by_product_id_and_property_id_and_value(
    product.id, property.id, d[descname]) 
10

Można również użyć where(...).first_or_create - ActiveRecord::Relation#first_or_create.

product_property_attrs = { product_id: product.id, 
          property_id: property.id, 
          value: d[descname] } 

product_property = ProductProperty.where(product_property_attrs).first_or_create 
5

W Rails 4, można użyć find_or_create_by(attr1: 1, attr2: 2) znaleźć lub stworzyć przez wiele atrybutów.

Można też zrobić coś takiego:

User.create_with(
    password: 'secret', 
    password_confirmation: 'secret', 
    confirmation_date: DateTime.now 
).find_or_create_by(
    email: '[email protected]', 
    admin: true 
) 

Jeśli trzeba tworzyć użytkownikowi pewnych atrybutów, ale nie można wyszukiwać według tych atrybutów.

Powiązane problemy