【问题标题】:accepts_nested_attributes_for :tags? Splitting and storing comma separated tags through associations接受嵌套属性:标签?通过关联拆分和存储逗号分隔的标签
【发布时间】:2013-01-21 18:48:33
【问题描述】:

我有一个列表模型。列表具有嵌入的标签(使用 Mongoid)。当用户创建列表时,他可以在文本字段中通过逗号分隔列表指定关联的标签。

如何通过 List 关联存储标签?我可以在 List 模型上使用 Accepts_nested_attributes_for :tags 吗,还是必须预处理标签字符串?

这是我目前所拥有的。如何处理标签字符串,将其拆分并将每个标签单独存储在作为列表一部分的嵌入式标签文档中?

列表控制器:

class ListsController < ApplicationController
  def new
    @list = List.new

    respond_to do |format|
      format.html # new.html.erb
      format.json { render json: @list }
    end
  end

  def create
    list_params = params[:list]
    list_params[:user_id] = current_user.id
    @list = List.new(list_params)
    if @list.save
     redirect_to @list, notice: 'List was successfully created.'
    else
      render action: "new"
    end
  end
end

列表创建表单

= form_for @list do |f|
  - if @list.errors.any?
    #error_explanation
      %h2= "#{pluralize(@list.errors.count, "error")} prohibited this list from being saved:"
      %ul
        - @list.errors.full_messages.each do |msg|
          %li= msg

  .field
    = f.label :name
    = f.text_field :name
  .field
    = f.label :description
    = f.text_field :description
  .field
    = f.fields_for :tags do |t|
      = t.label :tags
      = t.text_field :name
  .actions
    = f.submit 'Save'

列表模型

class List
  include Mongoid::Document
  include Mongoid::Timestamps
  field :name
  field :description
  embeds_many :items
  embeds_many :comments
  embeds_many :tags
  belongs_to :user

  accepts_nested_attributes_for :tags

标签模型

class Tag
  include Mongoid::Document
  field :name
  has_one :list
end

根据 Geoff 的建议进行修改

列表控制器最终看起来。

 def create
    tags = params[:tags][:name]
    list = params[:list]
    list[:user_id] = current_user.id
    @list = List.new(list)
    tags.gsub("\s","").split(",").each do |tag_name|
      @list.tags.new(:name => tag_name)
    end
    if @list.save
     redirect_to @list, notice: 'List was successfully created.'
    else
      render action: "new"
    end
  end

【问题讨论】:

    标签: ruby-on-rails mongoid rails-activerecord


    【解决方案1】:

    如果我理解正确的话,我认为你想做的是:

    您的视图将显示每个标签的标签名称字段,但在创建时没有关联的标签,所以我认为它只是不显示任何内容。

    使用:has_many 时,rails 会为您创建一个不错的小函数List.tag_ids。由于我不熟悉它,我假设:embeds_many 的功能是:has_many 的超集。这样做的重点是,如果您可以提供某种形式来收集 id,那么您就完成了。一组复选框可以工作,或者多选。以下是复选框的外观:

    = hidden_field_tag "list[tag_ids][]"
    - Tags.all.each do |t|
      = check_box_tag "list[tag_ids][]", t.id, t.list == @list, id: "list_tag_ids_#{t.id}"
      = label_tag "list_tag_ids_#{t.id}", t.name
    

    我在这里问过类似的问题:

    Rails: How do I transactionally add a has_many association to an existing model?

    但是,这不是您要求的。您可以使用 javascript 实现按名称关联标签的表单。这可能会很好,但会有点棘手。

    假设没有 javascript,如果您在视图中以逗号分隔列表的形式输入名称,则需要在控制器中对其进行解析。类似这样:

    查看:

    label_tag :tags
    text_field_tag :tags
    

    控制器:

    ...
    @list = List.new(list_params)
    params[:tags].gsub("\s","").split(",").each do |tag_name|
      tag = Tag.find_by_name(tag_name)
      @list.tags << tag if tag
    if @list.save
    ...
    

    我建议的解决方案都没有使用嵌套属性。我认为它们在这里不适用于您。当您尝试更新嵌套模型的属性时使用它们,但您只是尝试建立关联。

    希望对你有帮助。

    【讨论】:

    • 感谢 Geoff,这确实有很大帮助。我发布了基于您的帮助的最终解决方案的编辑。非常感谢!
    • 啊...我的印象是标签已经创建了。如果您混合了已创建和未创建的标签,您可能需要考虑@list.tags.find_or_initialize_by_name(tag_name)
    • 哦,等等,我认为这只会找到现有的标签关联,而不是所有标签。没关系!
    猜你喜欢
    • 2019-06-22
    • 2020-04-21
    • 2020-05-28
    • 2023-01-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多