2016-09-14 4 views
0

Ich habe drei Modelle mit einfachen Assoziationen.Erstellen Sie Eintrag für verschachteltes Modell mit has_many und durch

class User < ActiveRecord::Base 
    has_many :blogs 
end 

class Blog < ActiveRecord::Base 
    # Blog has 'title' column 
    belongs_to :user 
    has_many :entries 
end 

class Entry < ActiveRecord::Base 
    # Entry has 'article' column 
    belongs_to :blog 
end 

Ich mache eine JSON-API, um neuen Eintrag zu erstellen. Eine spezielle Anforderung besteht darin, einen Blog zu erstellen, falls dieser nicht existiert. Die JSON-Eingang sollte wie sein

{ "entry" : 
      { "article" : "my first blog entry", 
      "blog" : 
        { "title": "My new blog" } 
      } 
} 

Wenn der Blog den Eintrag in dem Blog existiert hinzuzufügen. Ich bin der Umsetzung ‚Einträge # erstellen‘ Methode und was ich will ist, etwas zu tun wie

def create 
    @user = Users.find(params[:user_id]) # :user_id is given in URL 
    # I want to do something like 
    # @user.entries.create(params[:entry]) 
    #  or 
    # @user.create(params[:entry]) 
    # but this doesn't work. 
end 

Was will ich hier fragen, wenn ich manuell die JSON erste analysieren und Blog-Objekt erstellen und dann erstellen Eintrag Objekt. Wenn es möglich ist, möchte ich, dass die Modelle solche Eingaben akzeptieren und korrekt funktionieren.

Eine andere mögliche Lösung ist es, die API zu ändern und es in Blogs Controller zu machen und JSON akzeptieren wie

{ "blog" : 
      { "title" : "My new blog", 
      "article_attributes" : 
        { "article": "my first blog entry" } 
      } 
    } 

aber wegen irgendwelchen Gründen, kann ich nicht die API wie diese machen. (Der erste Knoten des JSON muss "Eintrag" sein, nicht "Blog")

Was ich bisher versucht habe, ist "accept_nested_attributes_for" im Entry-Modell hinzuzufügen.

class Entry < ActiveRecord::Base 
    # Entry has 'article' column 
    belongs_to :blog 
    accepts_nested_attributes_for :blog 
end 

und dann Post JSON wie

{ "entry" : 
      { "article" : "my first blog entry", 
      "blog_attributes" : 
        { "title": "My new blog" } 
      } 
} 

dann in der Steuerung

@user.entries.create(params[:entry]) 

Es scheint, dass Rails versucht "Blog" Eintrag mit diesem Code zu erstellen, aber schlägt fehl, da die „blog_attributes "schließt 'user_id' nicht ein. Ich kann user_id zu den Parametern in meinem Controller hinzufügen, aber es sieht umständlich aus, da ich @user.entries.create schreibe, was sagen sollte, an welchem ​​Benutzer ich gerade arbeite.

Gibt es eine gute Möglichkeit, alles so zu machen, wie ich wollte? (? Oder mache ich etwas total falsch)

+0

Die 'accepts_nested_attributes_for' Funktionalität funktioniert anders. Sie können zulassen, dass Blog verschachtelte Attribute für Einträge akzeptiert, da die Beziehung auf diese Weise funktioniert. Wenn der Eintrag Attribute für sein Elternelement (das Blog) akzeptiert, scheint er etwas zurückgeblieben zu sein, nein? – Frost

+0

Ja, was ich mache ist das Gegenteil der üblichen Objekterstellung. Aber das möchte ich jetzt tun. 'access_nested_attributes_for' ist nur meine Probezeit und ich bin mir nicht sicher ob es funktioniert. Ich möchte wissen, ob es dafür einige gute Praktiken oder Muster gibt. –

+1

Ich denke, du musst den Blog erstellen, bevor du Einträge hinzufügst, also glaube ich nicht, dass "access_nested_attributes_for" dein Freund hier ist, leider. – Frost

Antwort

0

Ok accepts_nested_attributes_for :blog von Ihrem Einstiegsmodell entfernen

Und in Ihrem Blog-Modell setzte accepts_nested_attributes_for :entries, reject_if: :all_blank, allow_destroy: true

In Ihrem JSON dies tun:

{ "blog" : 
      { "title" : "My new blog", 
      "entry" : 
        { "article": "my first blog entry" } 
      } 
} 

In Ihrem blogs_controller.rb tun Sie dies:

def blog_params 
    params.require(:blog).permit(:id, :title, entries_attributes: [:id, :article, :_destroy]) 
end 

und in Ihrem blogs_controller.rb neue Aktion:

def new 
@blog = Blog.new 
@blog.entries.build 
end 

// in Ihrem blogs_controller Aktion erstellen:

def create 
    @user = Users.find(params[:user_id]) # :user_id is given in URL 
    @user.blog.create(blog_params) 
end 
+0

Wie ich in der Frage gesagt habe, kann es nicht akzeptiert werden, JSON zu verwenden, dessen erster Knoten "Blog" ist. –

Verwandte Themen