我无法将一个对象与HABTM关系中的另一个对象关联,只有在通过JSON POST创建新对象时(关系在使用Rails控制台时按预期工作)。
要重现:我创建了一个包含视频(包含标题和网址)和播放列表(有名称)的示例项目:
rails new videotest
cd videotest
rails g scaffold video title:string url:string
rails g scaffold playlist name:string
rails g migration create_playlists_videos playlist_id:integer video_id:integer
rake db:migrate
我在模型之间设置 has_and_belongs_to_many 关系:
class Playlist < ActiveRecord::Base
has_and_belongs_to_many :videos
end
class Video < ActiveRecord::Base
has_and_belongs_to_many :playlists
end
在视频控制器中,我白名单列出了playlist_ids参数:
def video_params
params.require(:video).permit(:title, :url, playlist_ids: [])
end
然后在rails控制台中创建一些示例对象:
Video.create!(title:"video1", url:"http://youtube.com/123")
Video.create!(title:"video2", url:"http://youtube.com/456")
@playlist = Playlist.create(name:"playlist1")
@playlist.videos.append([Video.first, Video.second])
Playlist.first.videos.count
按预期返回2,表明HABTM关系配置正确。
我可以使用AJAX POST请求成功创建一个新的Video对象,其中我还硬编码了第一个播放列表的ID:
data = JSON.stringify({
"title": "test video",
"url": "http://www.youtube.com/987",
"playlist_ids": [1]
});
$.ajax({
url: "http://" + window.location.host + "/videos.json",
type:"POST",
contentType:"application/json; charset=utf-8",
dataType:"json",
data: data,
success: function(msg) {
console.log("added " + msg.title)
}
});
问题:未使用播放列表_id且生成的视频对象与播放列表1无关。
create
方法包括:
def create
@video = Video.new(video_params)
我注意到video_params
并未包含playlist_id,但params
确实包含:
(byebug) video_params
{"title"=>"test video", "url"=>"http://www.youtube.com/987"}
(byebug) params[:playlist_ids]
[1]
为什么没有playlist_ids
通过白名单?
答案 0 :(得分:3)
如果这些关联设置正确,则您的播放列表模型应具有video_ids属性,并且您的视频模型应具有playlist_ids属性。
您可以通过表单传递这些内容,rails应该在您的播放列表_视频链接表中创建相应的记录。
因此,在您的 VideosController 中设置白名单,如下所示:
def video_params
params.require(:video).permit(:title, :url, playlist_ids: [])
end
现在调整你的ajax调用来传递一个playlist_ids数组,如下所示:
JSON.stringify({ "video": {"title": title, "url": "http://www.youtube.com", "playlist_ids": [1,2]}})
请记住将参数嵌套在“视频”节点中。
因此,在这种情况下,您要将视频与playlist_id 1和playlist_id 2相关联,例如。
答案 1 :(得分:1)
当您使用habtm
时,您将获得几种应该使用的方法:
具体来说,如果您想在创建时设置playlist_id
的{{1}},那么您最好填充video
属性:
playlist_ids
这会覆盖与$.ajax({
url: "http://" + window.location.host + "/videos.json",
type:"POST",
contentType:"application/json; charset=utf-8",
dataType:"json",
data: JSON.stringify({"title": title, "url": "http://www.youtube.com", "playlist_ids": [1]}),
success: function(msg) {
console.log("added " + msg.title)
}
});
#app/controllers/videos_controllers.rb
class VideosController < ApplicationController
def create
@video = Video.new video_params
@video.save
end
private
def video_params
params.require(:video).permit(:title, :url, playlist_ids: [])
end
end
相关联的当前playlists
;这意味着如果您想添加 / 删除视频到播放列表,您最好使用video
和<<
方法。
如果需要,我可以解释如何执行此操作。