首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >多态模型的collection_select

多态模型的collection_select
EN

Stack Overflow用户
提问于 2017-09-20 08:46:17
回答 1查看 309关注 0票数 1

我在Rails 5.1.3应用程序中将Tag设置为多态模型。我正在尝试设置一个collection_select,以便从下拉列表中选择标记。

表单创建新的标记,关联工作得很好,但是,我无法获得传递给表单的标记名,所以我的标记将name保存为空字符串。

_form.html.erb

代码语言:javascript
运行
复制
<%= form_for [taggable, Tag.new] do |f| %>
  <%= f.collection_select :taggable_id, Tag.order(:name), :id, :name %>
  <%= f.submit %>
<% end %>

tags_controller.rb

代码语言:javascript
运行
复制
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:

代码语言:javascript
运行
复制
=> <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

代码语言:javascript
运行
复制
class Book < ApplicationRecord
  has_many :tags, as: :taggable
end

tag.rb

代码语言:javascript
运行
复制
class Tag < ApplicationRecord
 belongs_to :taggable, polymorphic: true
end

标签表

代码语言:javascript
运行
复制
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
EN

Stack Overflow用户

回答已采纳

发布于 2017-09-20 10:49:01

问题是你处理这个问题是非常错误的。

标记只能属于单个资源的标记系统作为分类法几乎毫无价值。相反,您需要与一个联接表进行多到多的关联:

代码语言:javascript
运行
复制
# 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上设置多个标记,可以使用ActiveRecord为has_many关联创建的tag_ids=设置器:

代码语言:javascript
运行
复制
<%= form_for(@book) do |f| %>
  <%= f.text_input :title %>
  <%= f.collection_select :tag_ids, Tag.order(:name), :id, :name, multiple: true %>
  <%= f.submit %>
<% end %>

这是taggable (父)资源的常规创建/更新操作的一部分。一次创建一个标签(创建一个连接记录)是可以完成的,但并不是很有用。

另一方面,POST /books/:book_id/tags将用于创建单个标记并建立关联:

代码语言:javascript
运行
复制
<%= form_for([@taggable, @tag]) do |f| %>
  <%= f.label :name do %>
    <%= f.text_input :name %>
  <% end %>
  <%= f.submit %>
<% end %>
代码语言:javascript
运行
复制
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请求来让用户“内联”创建标记,从而提供一个更好的UX。

票数 3
EN
查看全部 1 条回答
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/46317357

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档