Rails中无法向SQLite中间表保存记录的问题求助
我看了你的代码,问题出在表单参数命名和强参数配置这两个核心点上——手动设置category_ids能成功,说明关联本身是没问题的,只是表单提交的参数没被正确处理。下面一步步给你修正:
1. 修正表单中的选择框参数名
你的表单里用了f.select(:category_id, ..., :multiple => true),但对于has_and_belongs_to_many关联,Rails期望的参数是复数形式的category_ids(因为支持多选分类),把这行改成:
<%= f.select(:category_ids, @categories.map{|t| [t.name, t.id]}, {}, :multiple => true, :class => 'custom-select') %>
2. 修正强参数(video_params)配置
你现在的video_params里用了category_attributes: [:id],这是给accepts_nested_attributes_for用的配置,但你用的是HABTM关联,不需要这个。应该改成允许接收数组类型的category_ids参数:
def video_params params.require(:video).permit(:title, :url, :description, category_ids: []).merge(user_id: session[:user_id]) end
这里category_ids: []表示允许接收一个数组类型的参数,对应多选的分类ID。
3. 移除create方法里的错误代码
你在create里写的@video.category_ids = [video_params]完全错误——video_params是整个参数哈希,把它放进数组赋值给category_ids会直接导致类型错误。直接删掉这行,因为Video.new(video_params)已经会自动处理category_ids参数了。修正后的create方法:
def create @video = Video.new(video_params) if @video.save flash[:notice] = 'The movie has been added successfuly' redirect_to(:action => 'index') else @categories = Category.all render('new') end end
最后验证关联表结构
你的Video模型里的has_and_belongs_to_many :categories是正确的,记得确认中间表的命名和结构:Rails对HABTM中间表的命名要求是两个模型名按字母顺序排列的复数形式,也就是categories_videos(因为category在video前面),表只需要两个外键字段:category_id和video_id,不需要额外的主键。
做完这些修改后,表单提交的分类ID就能正确保存到中间表了。
内容的提问来源于stack exchange,提问作者Radek

