0

我有一个列表模型。列表具有嵌入的标签(使用 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
4

1 回答 1

1

If I understand you correctly, here's what I think you want to do:

Your view as it is will display a tag name field for each tag, but there are no associated tags at create time so I assume it just doesn't show anything.

When using a :has_many, there is a nice little function that will be created for you by rails called List.tag_ids. Since I am not familiar with it, I am assuming the functionality of :embeds_many is a superset of of :has_many. The point of this is that if you can provide some sort of form which gathers the ids, then you'd be done. A set of checkboxes could work, or a multi-select. Here is what checkboxes might look like:

= 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

I asked something similar here:

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

However, this isn't what you asked for. You could achieve a form which associates tags by name by using javascript. That would probably be nice, but it would be a bit tricky.

Assuming no javascript, if you are inputting the names as a comma separated list in the view, you will need to parse it in the controller. Similar to this:

View:

label_tag :tags
text_field_tag :tags

Controller:

...
@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
...

None of the solutions I suggested make use of nested attributes. I don't think they are applicable for you here. They are used when you are trying to update the attributes of the nested model, but you're just trying to make the association.

I hope that helps.

于 2013-01-15T21:04:21.870 回答