2017-09-20 85 views
1

我有Tag在我的Rails 5.1.3應用程序中設置爲多態模型。我試圖設置一個collection_select,以便我可以從下拉列表中選擇標籤。collection_select爲多態模型

表單創建新標籤並且關聯工作得很好,但是,我無法將標籤名稱傳遞到表單中,因此我的標籤將name保存爲空字符串。

_form.html.erb

<%= form_for [taggable, Tag.new] do |f| %> 
    <%= f.collection_select :taggable_id, Tag.order(:name), :id, :name %> 
    <%= f.submit %> 
<% end %> 

tags_controller.rb

class TagsController < ApplicationController 
before_action :authenticate_user! 

def create 
    @tag = @taggable.tags.new(tag_params) 
    @tag.user_id = current_user.id 

    if @tag.save 
    redirect_to book_path(@taggable.book_id), notice: "Tag saved" 
    else 
    redirect_to root_path, notice: "Sorry, something went wrong" 
    end 
end 

private 

    def tag_params 
    params.require(:tag).permit(:name) 
    end 

標籤PARAMS:

=> <ActionController::Parameters {"utf8"=>"✓", "authenticity_token"=>"z2PLrvETqtq742zmr3pghEYYqoGoLv05gLP3OXopLM+blWWw+HmR4AMMDB+5ET3E5YLXeyhMCFMHfdxJNHlkZA==", "tag"=><ActionController::Parameters {"taggable_id"=>"1"} permitted: false>, "commit"=>"Create Tag", "controller"=>"books/tags", "action"=>"create", "book_id"=>"26"} permitted: false> 

編輯:增加車型和字段

book.rb

class Book < ApplicationRecord 
    has_many :tags, as: :taggable 
end 

tag.rb

class Tag < ApplicationRecord 
belongs_to :taggable, polymorphic: true 
end 

標籤表

create_table "tags", force: :cascade do |t| 
    t.string "taggable_type" 
    t.integer "taggable_id" 
    t.integer "user_id" 
    t.text "name" 
    t.datetime "created_at", null: false 
    t.datetime "updated_at", null: false 
end 
+0

請在模型中添加模型和字段? – Ankit

+0

@Ankit完成.... – BillyBib

回答

2

的問題是,你正在接近這個問題非常錯誤的。

一個標籤系統,一個標籤只能屬於一個資源,與分類標準相差無幾。相反,你想要一個多對多關聯用一個連接表:

# app/models/tag.rb 
class Tag < ApplicationRecord 
    has_many :taggings 
    has_many :taggables, through: :taggings 
end 

# This join model represents a tag attached to a resource 
# app/models/tagging.rb 
class Tagging < ApplicationRecord 
    belongs_to :tag 
    belongs_to :taggable, polymorphic: true 
end 

# We extract the taggable feature to a concern so that we don't have to repeat it. 
# app/models/concerns/taggable.rb 
module Taggable 
    extends ActiveSupport::Concern 

    included do 
    has_many :taggings, as: :taggable 
    has_many :tags, through: :taggings 
    end 
end 

# app/models/book.rb 
class Book < ApplicationRecord 
    include Taggable 
end 

# just an example 
class Film < ApplicationRecord 
    include Taggable 
end 

這採用tags作爲標準化表替代該表中一遍又一遍重複的名字。這使您可以在不使用文本搜索的情況下獲取具有特定標籤的書籍,這些搜索比在索引列上使用連接要慢得多。

設置對Taggable多個標籤,你會使用tag_ids=二傳手其中的ActiveRecord創建has_many關聯:

<%= form_for(@book) do |f| %> 
    <%= f.text_input :title %> 
    <%= f.collection_select :tag_ids, Tag.order(:name), :id, :name, multiple: true %> 
    <%= f.submit %> 
<% end %> 

這是作爲加標籤(父)資源正常創建/更新行動的一部分進行。一次創建一個標記(創建一個連接記錄)可以完成,但不是很有用。

POST /books/:book_id/tags會,另一方面可用於創建一個標籤,並建立關聯:

<%= form_for([@taggable, @tag]) do |f| %> 
    <%= f.label :name do %> 
    <%= f.text_input :name %> 
    <% end %> 
    <%= f.submit %> 
<% end %> 

class TagsController 
    before_action :set_taggable 

    # POST /books/:book_id/tags 
    def create 
    @tag = @taggable.tag.new(tag_params) 

    if @tag.save 
     redirect_to @taggable, success: "New tag created." 
    else 
     render :new 
    end 
    end 

    def set_taggable 
    @taggable = Book.find(params[:book_id]) 
    end 

    def tag_params 
    params.require(:tag).permit(:name) 
    end 
end 

但是一個體面的使用Ajax可以讓用戶創建標籤「內聯「通過發送POST /tags請求來提供更好的用戶體驗。

+0

感謝你 - 你是完全正確的我得到的分類錯誤。還有一件事:如果我想讓每個用戶都擁有自己的書籤,我將如何修改代碼?當時,所有用戶都可以看到所有標籤,而不僅僅是他們創建的標籤。我試圖在標籤表上添加一個user_id列並在'tags_controller'中設置該值,但似乎不起作用。 – BillyBib

+0

我有點避免,因爲它已經夠複雜了。如果您想添加所有權 - 請將用戶標識列添加到標記。 – max

+0

但我鼓勵你特意提出一個新的問題 – max