Rails 3: Multiple Wählen Sie mit has_many über Assoziationen

Ich möchte die Möglichkeit haben, mehrere Kategorien für einen Beitrag mit mehreren Auswahlmöglichkeiten auszuwählen.

Ich habe folgende Modelle: Post, Category und PostCategory.

class Post  :post_categories end class Category  :post_categories end class PostCategory < ActiveRecord::Base has_one :post has_one :category belongs_to :post # foreign key - post_id belongs_to :category # foreign key - category_id end 

In meinem Controller habe ich etwas wie @post = Post.new. Ich habe einige Kategorien erstellt.

Und im Blick habe ich:

    true %>   

Und … wo sind meine Kategorien? Ich habe nur “mehrere” in ausgewählten Optionen. Ich denke, dass etwas mit meiner Form nicht stimmt.

Es tut mir leid, die Toten wieder auferstehen zu lassen, aber ich fand eine viel einfachere Lösung, die es ermöglicht, den standardmäßigen Controller-Aktionscode zu verwenden und die ActiveModel-Setter-Logik für eine has_many zu verwenden. Ja, es ist total magisch.

 < %= f.select :category_ids, Category.all.collect {|x| [x.name, x.id]}, {}, :multiple => true %> 

Wenn Sie den Param-Namen “category_ids” (oder “your_collection_ids”) verwenden, wird Rails automatisch angewiesen, @ post.category_ids = params [: post] [: category_ids] aufzurufen, um die Kategorien für diesen Post entsprechend einzustellen, ohne den Standardcontroller / das Gerüst zu ändern #create und #update code.

Oh, und es funktioniert mit has_many: etwas, durch:: something_else, automatisch das Join-Modell zu verwalten. Absolut fantastisch.

Ändern Sie daher vom OP aus einfach den Feld- / Parameternamen in: category_ids anstelle von: categories.

Dadurch werden auch die ausgewählten Kategorien des Modells automatisch in das Auswahlfeld eingefügt, das in einem Bearbeitungsformular markiert ist.

Verweise:

Aus den has_many-API-Dokumenten, in denen ich das gefunden habe.

Auch die Warnung aus dem Formularhelfer-Handbuch erklärt diesen “Typenkonflikt”, wenn nicht der richtige Formularfeld- / Parametername verwendet wird.

Durch Verwendung des richtigen Formularfeld- / Parameternamens können Sie Formulare neu formatieren und bearbeiten und die Controller dünn halten, wie es von der Rails-Methode unterstützt wird.

Hinweis für Rails 4 und starke Parameter:

 def post_params params.require(:post).permit(:title, :body, category_ids: []) end 

Endgültige Lösung, um Kategorien in Ihren Posts zu organisieren, ich hoffe, es wird nützlich sein.

Um mehrere zu verwenden, brauchen wir select_tag:

 < %= select_tag "categories", options_from_collection_for_select(Categories.all, 'id', 'name'), :multiple => true %> 

Oder f.select ( vielen Dank an Tigraine und Brent! ), Es ist eleganter Weg:

 < %= f.select :categories, Category.all.collect {|x| [x.name, x.id]}, {}, :multiple => true %> 

In der Aktion unseres Controllers brauchen wir:

 def create @post = Post.new(params[:post]) if @post.save params[:categories].each do |categories| categories = PostCategory.new(:category_id => categories, :post_id => @post.id) if categories.valid? categories.save else @errors += categories.errors end end redirect_to root_url, :notice => "Bingo!" else render "new" end end 

Was Sie brauchen, ist eine Liste von Optionen für die Auswahl:

 < %= f.select :category_id, Category.all.collect {|x| [x.name, x.id]}, :multiple => true %> 

Tigraine hatte es fast, aber Sie müssen einen zusätzlichen leeren Hash angeben:

< %= f.select :category_id, Category.all.collect {|x| [x.name, x.id]}, {}, :multiple => true %>

Da die @post keine ID hat, zeigt das from möglicherweise keine Kategorien an, da keine Verknüpfung besteht. Sie müssen einen Build auf @post etwas wie tun

  @post = Post.new(:categories => Category.all)