如何在ActiveRecord中保存带有多对多关系的标签

问题描述:

我正尝试使用多对多标签创建视频。所以,每个标签将在Tag表中的每一行中。我不确定自己必须自己做,还是Rails有一些可以做到的魔法?如何在ActiveRecord中保存带有多对多关系的标签

这是我的模型。

class Video < ActiveRecord::Base 
    belongs_to :user 

    has_many :video_tags 
    has_many :tags, through: :video_tags 
end 

class Tag < ActiveRecord::Base 
end 

class VideoTag < ActiveRecord::Base 
    belongs_to :video 
    belongs_to :tag 
end 

这里是我的形式

<%= form_for(@video, html: { class: "directUpload" }, multipart: true) do |f| %> 
    <% if @video.errors.any? %> 
    <div id="error_explanation"> 
     <h2><%= pluralize(@video.errors.count, "error") %> prohibited this user from being saved:</h2> 

     <ul> 
     <% @video.errors.full_messages.each do |message| %> 
     <li><%= message %></li> 
     <% end %> 
     </ul> 
    </div> 
    <% end %> 

    <div class="field"> 
    <%= f.label :title %><br> 
    <%= f.text_field :title %> 
    </div> 
    <div class="field"> 
    <%= f.label :path %><br> 
    <%= f.file_field :path%> 
    </div> 
    <div class="field"> 
    <%= f.label :tags %><br> 
    <%= f.text_field :tags %> 
    </div> 
    <div class="actions"> 
    <%= f.submit %> 
    </div> 
<% end %> 

这是我的Controller

class VideosController < ApplicationController 
    def show 
     @videos = Video.where(user_id: params[:user_id]) 

    end 

    def new 
     @video = Video.new 
    @s3_direct_post = S3_BUCKET.presigned_post(key: "uploads/#{SecureRandom.uuid}/${filename}", success_action_status: 201, acl: :public_read) 
    end 


    def create 
    @video = Video.new(video_params) 
    @video.user_id = 1 
    if @video.save 
     redirect_to @video 
    end 
    end 

    private 
    # Use callbacks to share common setup or constraints between actions. 

    # Never trust parameters from the scary internet, only allow the white list through. 
    def video_params 
     params.require(:video).permit(:title, :path, :tags) 
    end 

end 

但后来我得到这个错误,我想我一定是错过了一些东西。我只想让标签以空格分隔。

Started POST "/videos" for ::1 at 2015-04-07 00:21:11 -0400 
Processing by VideosController#create as HTML 
    Parameters: {"utf8"=>"✓", "authenticity_token"=>"authenticity_token", 

“视频”=> { “标题”=> “asdfasdf”, “路径”=> “// s3.amazonaws.com/uploads/token/57203191c21df0cacf98f3fa9340f4.mp4”, “标签 “=>” 测试 “}, ”提交“=>” 创建视频“} 完成500内部服务器错误在3ms的

NoMethodError (undefined method `each' for "test ":String): 
    app/controllers/videos_controller.rb:14:in `create' 
+0

当您尝试从UI创建视频时,您可以发布您的服务器日志吗? – Surya

+0

更新了问题。 – toy

+0

我在videos_controller的行号14中看不到'each'。你有没有在你的问题上发布的东西? – Surya

我以下的答案将会有助于你 https://stackoverflow.com/questions/22611372/rails-4-paperclip-and-polymorphic-association

可以使用accept_nested_attributes_for和,

<%= f.fields_for :tags, @_your_tags do |t| %> 

,而不是

<div class="field"> 
    <%= f.label :tags %><br> 
    <%= f.text_field :tags %> 
</div> 
+0

这是否意味着我有多个文本字段? – toy

+0

是的,它有多个文本字段。但标签输入一些jQuery将帮助您为单个文本字段标记而不是'f.fields_for'。只有参数需要像'{videos => {tags => ['a','b']}}' –

我发现this wiki非常有益的。是的,轨道有一个特殊的方式来处理这个问题。这些被称为嵌套模型,或者您也可以用户nested_form宝石

你的联系会是这样的:

class Video < ActiveRecord::Base 
    belongs_to :user 

    has_many :video_tags 
    has_many :tags, through: :video_tags 
end 

class VideoTag < ActiveRecord::Base 
    belongs_to :video 
    belongs_to :tag 
end 

class Tag < ActiveRecord::Base 
    has_many :video_tags 
    has_many :videos, through :video_tags 
end