2016-06-21 14 views
2

ich folgende Modelle haben:Rails 4 find_or_create_by mit accepts_nested_attributes

class Foo < ActiveRecord::Base 
    belongs_to :bar 
    accepts_nested_attributes_for :bar 
end 

class Bar < ActiveRecord::Base 
    has_many :foo 
end 

Bar enthält 'Objekt' und Foo enthält 'label'.

Ich kann folgendes tun:

f=Foo.create(:label=>"label",:bar_attributes=>{:object=>"mason jar"}) 

Dies funktioniert gut.

jedoch, was ich will zu tun ist:

f=Foo.find_or_create_by(:label=>"label",:bar_attributes=>{:object=>"mason jar"}) 

Das Problem ist, scheitert dies mit einem SQL-Fehler

ActiveRecord::StatementInvalid: SQLite3::SQLException: no such column: bar_attributes.object: SELECT "foo".* FROM "foo" WHERE "foo"."label" = ? AND "bar_attributes"."object" = 'mason jar' LIMIT 1 

Ich kann verstehen, warum dies geschieht, aber ich will um diese Funktionalität nutzen zu können. Ich weiß, dass ich Code hinzufügen muss, um den "find_or_create_by" für Bar zu machen, aber ich habe das bereits funktioniert, also mache ich das hier nicht, nur das Problem, das ich gerade habe.

Also, gibt es eine Möglichkeit, das 'Finden' für Foo nur IGNORE bar_attributes zu machen, und nur verwenden, wenn es notwendig ist (für das Erstellen)?

Oder gibt es einen anderen Weg, dies zu erreichen?

EDIT: Eine Erklärung, warum dies der Weg ist, es ist:

Wir haben zwei getrennte Objekte. Bar ist ein eigenständiges Objekt. Foo ist ein separater Objekttyp, der einen Balken enthält.

So konnten wir mehrere Datensätze in Bar haben:

Mason jar 
Shovel 
Can of corn 

Und könnten wir andere Datensätze in Foo haben:

label: 123 => Bar: Shovel 
label: 456 => Bar: Shovel 
label: 123 => Bar: Can of corn 

All Bar ist in Foo gelten Bar ist, aber nur Bar ist mit Etiketten in Foo sind ein Foo.

Also, im Grunde, ich will laufen können:

f = Foo.find_or_create_by(:label=>'label',:bar_attributes=>{:object='object'}) 

und habe es die Bar schaffen, wenn nötig, dann die Foo erstellen, wenn nötig.

Ich hoffe, das hilft.

+0

Sie können find_or_create_by mit: wo oder einem benutzerdefinierten Bereich verketten. Haben Sie versucht, vor der Verwendung 'find_or_create_by' eine where-Klausel zu verwenden? –

+0

Nun, im Allgemeinen waren verschachtelte Attribute einmal ein Juwel, das später in Rails integriert wurde. Daher muss alles, was auf ActiveRecord zutrifft, nicht mit verschachtelten Attributen arbeiten. Versuchen Sie, ein Foo-Objekt nur dann zu erstellen, wenn ein Bar-Objekt mit einigen Attributen nicht existiert? –

+0

Nicht der gesamte Code ist oben. Kurz gesagt, was ich tun möchte, ist eine find_or_create_by auf Bar, und dann verwenden Sie das Ergebnis für die find_or_create_by auf Foo. –

Antwort

1

Ich denke, Sie es wie folgt tun:

f = Foo.find_or_create_by(label: 'label', bar: Bar.find_or_create_by(object: 'object')) 

Es entspricht

f = Foo.find_or_create_by (Label: 'label', bar_id: Bar.find_or_create_by (Objekt: ' object '). id)

Sie könnten es zwei Zeilen machen, um zu überprüfen, ob Bar erstellt wurde (ohne Validierungsfehler).