我有负责创建Foobar的“快速添加”表单。一旦提交/保存,您将返回到表单以添加下一个 Foobar。我现在有要在创建 Foobar 时添加到的多态任务。在这种情况下,任务不需要任何详细信息,因此我选择在表单上设置一个复选框,上面写着“执行此任务”。如果在提交表单时选中,我希望创建一个任务并将其关联到 Foobar。
这样做并不难,但我正在努力寻找似乎是“正确”的做法。
选项 1: Foobar 接受_nested_attributes_for 任务,因此我可以创建嵌套表单,但实际上没有什么可嵌套的。该复选框不代表任务上的有效字段,只是我希望创建任务。我可以使用@foobar.build_task 并在表单中为任务放置一些隐藏字段,但如果未选中复选框,我必须使用 JS voodoo 来防止字段提交。这似乎是肮脏和错误的。
选项 2:我可以在 FoobarController#create 中放置一些逻辑,以查找复选框并在保存之前将任务构建到 Foobar 上。这里的问题是 Task 是多态的,也可能与其他事物相关联。甚至可能有多种“类型”的任务与正在创建的单个 Foobar 相关联。我认为这个解决方案比选项 1 更好,但不是很干燥。控制器中的任何此类逻辑最终都会在控制器中被复制以用于其他任务。
选项 3:在 Foobar 上有一个 before_save,它查找名为“create_task”的伪字段的存在,然后构建任务。这会将副本从控制器中移出并放入可任务模型中,但它并不比每个模型中重复的“has_many :tasks”行更多。尽管如此,寻找这样一个领域并采取行动似乎并不是模型的工作。
所以....我真的很感激一些想法。
更新#1:一些额外的信息......
一个任务也有一个创建者和一个受让人,两者都是系统中的用户。应该根据 current_user 方法自动分配创建者,这当然在 View 和 Controller 中可用,但在模型中不可用。我认为立即排除了答案纯粹基于模型的可能性(例如选项 3)。我认为它还暗示答案不是基于视图的(例如选项 1),因为应该将用户设置在服务器端,使其无法被篡改。所以也许答案就在控制器的某个地方?也许某种帮助方法来包装要在每个处理可任务事物的控制器中复制的逻辑?
更新#2:我目前的倾向......
我花了一些时间与一位受人尊敬的开发人员朋友交谈,并进一步确信答案最接近选项 2。视图和模型似乎都是错误的。控制器是有道理的,但主要问题是重复代码的可能性。我认为答案将是找到最佳方法来分解控制器代码,该控制器代码处理任务(或其他多态事物,如评论、文件上传等)与控制器负责的对象的附件。当我有一个我满意的解决方案时,我会尝试在这里发布。感谢大家的意见和建议!