我目前有一个专辑/艺术家数据库,它使用多个连接表来表示艺术家何时与专辑相关。他们可以被列为作曲家、编曲者或表演者。那是:
class Artist < ActiveRecord::Base
...
has_and_belongs_to_many :albumbycomposers, :class_name => "Album", :join_table => "albums_composers"
has_and_belongs_to_many :albumbyarrangers, :class_name => "Album", :join_table => "albums_arrangers"
has_and_belongs_to_many :albumbyperformers, :class_name => "Album", :join_table => "albums_performers"
...
end
和
class Album < ActiveRecord::Base
has_and_belongs_to_many :composers, :class_name => "Artist", :join_table => "albums_composers"
has_and_belongs_to_many :arrangers, :class_name => "Artist", :join_table => "albums_arrangers"
has_and_belongs_to_many :performers, :class_name => "Artist", :join_table => "albums_performers"
...
end
此代码用于在数据库中查找现有艺术家,然后创建关联。如果不存在艺术家,那么我使用 .build 方法来创建艺术家。
class AlbumsController < ApplicationController
...
def create
@album = Album.new(params[:album])
params["Composer Names"].each do |each|
if each.empty? == false
@exists = Artist.find_by_name(each)
if @exists.nil? == true
@album.composers.build(:name => each)
else
@album.composers << Artist.find_by_name(each)
end
end
end
params["Arranger Names"].each do |each|
if each.empty? == false
@exists = Artist.find_by_name(each)
if @exists.nil? == true
@album.arrangers.build(:name => each)
else
@album.arrangers << Artist.find_by_name(each)
end
end
end
...
end
...
end
当我尝试以作曲家和编曲者的身份输入新艺术家时,就会遇到问题。例如,假设我将此作为发布请求提交
Parameters: {"Name"=>["New Album"],
"Performer Names"=>["New Artist"],
"Composer Names"=>["New Artist"],
"Arranger Names"=>["New Artist"],
...
}
由于作曲家参数是第一位的,因此 rails 会正确解释它们(就好像艺术家不存在一样)。编曲者和表演者的论点也被解释为艺术家不存在。然后 rails 开始将数据插入我的数据库。首先创建专辑并将其插入专辑表,然后创建“新艺术家”并将其插入专辑作曲家(根据 .build 方法)。
但是,对于arranger和performer参数,build方法不能再使用,因为artist已经创建,所以代码没有正确执行。
对于这种特定情况,我尝试通过在编曲者和表演者参数行中使用 push 方法(又名 <<)来解决此问题,但这不起作用,因为它会立即触发而无需等待作曲家参数制作艺术家,导致在“找不到艺术家”错误中。以供参考:
collection<<(object, …)
Adds one or more objects to the collection by creating associations in the join table (collection.push and collection.concat are aliases to this method).
Note that this operation instantly fires update sql without waiting for the save or update call on the parent object.
处理这个问题的正确方法是什么?