嘿 不是Rails noob,但这让我很难过。 在Rails中有许多通过关联。当我通过葡萄酒单协会(或通过)表格将葡萄酒大量分配到酒吧时。
class WineBarController
def update
@winebar = WineBar.find(params[:id])
@winebar.wines = Wine.find(params[:wine_bar][:wine_ids].split(",")) // Mass assign wines.
render (@winebar.update_attributes(params[:wine_bar]) ? :update_success : :update_failure)
end
end
这将删除与该酒吧相关联的每个酒单行。然后它找到wine_ids中的所有葡萄酒,我们认为这是一个逗号分隔的葡萄酒ID。然后它将一个新的关联插入到winelist中。这将是昂贵的,但如果被破坏的关联行没有元数据,例如每个酒吧的每个玻璃和瓶子的价格,那就很好。
有没有办法让它不会吹走所有东西,只需对数组进行可枚举的比较,然后插入删除任何更改。我觉得这就是rails所做的事情,我只是错过了一些明显的东西。
感谢。
答案 0 :(得分:2)
您的问题看起来与更新方法中的第一个语句一样 - 您正在创建新的酒吧记录,而不是加载现有记录并更新它。这就是为什么当你检查记录时,没有任何关系的显示。 Rails 足够聪明,不会删除/创建列表中的每条记录,所以不要担心。
如果您正在为表单使用标准导轨设置:
<% form_for @wine_bar do |f| %>
然后你可以这样调用你的更新:
class WineBarController
def update
@winebar = WineBar.find(params[:id])
render (@winebar.update_attributes(params[:wine_bar]) ? :update_success : :update_failure)
end
end
您无需使用params[:wine_bar][:wine_ids]
明确更新记录,因为当您使用params[:wine_bar]
更新记录时,wine_ids已包含在其中。我希望这有帮助!
更新:您提到这不起作用,因为表单的设置方式,但您可以轻松修复它。在表单中,您需要将输入字段从wine_bar[wine_ids]
重命名为wine_bar[wine_ids_string]
。然后你只需要在你的模型中创建访问器,如下所示:
class WineBar < ActiveRecord::Base
def wine_ids_string
wines.map(&:id).join(',')
end
def wine_ids_string= id_string
self.wine_ids = id_string.split(/,/)
end
end
上面的第一个方法是“getter” - 它获取相关wine id的列表并将它们转换为表单可以使用的字符串。下一个方法是“setter”,它接受逗号分隔的id字符串,并将其分解为wine_ids=
接受的数组。
您可能也对我的文章Dynamic Form Elements in Rails感兴趣,该文章概述了rails表单输入的方式不仅限于数据库记录中的属性。可以使用任何一对存取方法。