Rails RESTful 删除嵌套资源
好的,这是一个示例场景。有一个学生资源 resources :students
,并且 Students 拥有并属于许多集合:resources :clubs
、resources :majors
等
。我们可以很容易地设置我们的路线...
resources :clubs do
resources :students
end
resources :majors do
resources :students
end
resources :students do
resources :clubs
resources :majors
end
这会为我们生成一堆标准的 RESTful 路线
- /clubs
- /clubs/:id
- /clubs/:club_id/students
- /clubs/:club_id/students/:id
- /majors
- /majors/: id
- /专业/:专业ID/学生
- /专业/:专业ID/学生/:ID
- /学生
- /学生/:ID
- /学生/:学生ID/俱乐部
- /学生/:学生ID/俱乐部/:ID
- /学生/:学生ID/专业
- / Students/:student_id/majors/:id
这是我的问题。使用 REST 语义,如何删除学生的专业? 浏览专业 /majors/:major_id/students/:id
下的学生将显示该学生在特定专业的“集合”中。但是删除 :id 的路由指向 StudentsController#destroy
,这会完全删除学生。哎呀!因此,也许我们采取另一种方式,对 /students/:student_id/majors/:id
处的资源执行 DELETE,现在这所学校不再提供 UnderwaterBasketweaving...哎呀!
现在,我们可以设置 ClubsController、MajorsController 或 StudentsController 的 destroy 方法来查找club_id、major_id 或student_id,但假设我们还想添加 Fraternities 和 GraduatingClasses 等。每个班级都将开始由巨大的开关条件组成,寻找存在的参数...然后找到顶部资源的集合并删除底部资源,反之亦然。 模型本身应该决定是否在没有更多关联记录的情况下删除自己...该资源上的“销毁”实际上已经变得用词不当...
更简单的方法来做到这一点?即使像 make_resourceful
或 resource_controller
这样流行的 Restful Rails 插件,在将 UnderwaterBasketweaving 从 Joe 的 Majors 中删除时也会将其吹走,或者在将 JohnDoe 从主要的 UnderwaterBasketweaving 中删除时将其完全删除。似乎有可能通过查看关联来理解语义的预期效果以及“破坏”应该做什么。
话又说回来,我是不是看错了?这不是UnderwaterBasketweaving -> 吗? Joe 而是 UnderwaterBasketweaving+Joe 作为单个资源,我们要删除的实际上不是 Joe,也不是 UnderwaterBasketweaving,而是代表该组合的资源?然而,当控制器是学生和专业时,这并不容易,它们实际上代表同名的资源(MVC实际上已经变成了RV......采用“约定”方法,而不是开发可能与模型名称,或到达它的路径)因此您将删除专业或学生;选择你的毒药...
如何避免在关联资源的无限图中管理条件,当希望删除位于集合的上下文中而不属于其奇点时,删除实际上不是意图...?
...major.student.delete
... 有没有办法让“student”ActiveRecord 对象知道它在以“major”AR 对象开头的方法链中发送了“删除”消息?
Okay, so here's an example scenario. There is a student resource resources :students
, and students has and belongs to many collections: resources :clubs
, resources :majors
, etc.
So we can set up our routes easily enough...
resources :clubs do
resources :students
end
resources :majors do
resources :students
end
resources :students do
resources :clubs
resources :majors
end
which generates us a bunch of standard RESTful routes
- /clubs
- /clubs/:id
- /clubs/:club_id/students
- /clubs/:club_id/students/:id
- /majors
- /majors/:id
- /majors/:major_id/students
- /majors/:major_id/students/:id
- /students
- /students/:id
- /students/:student_id/clubs
- /students/:student_id/clubs/:id
- /students/:student_id/majors
- /students/:student_id/majors/:id
So here's my question. With REST semantics, how would one delete a major for a student?
Browsing students under a major /majors/:major_id/students/:id
would show that student in the specific major's 'collection'. But the route for deleting an :id, points to StudentsController#destroy
, which would delete the student completely. Whoops! So maybe we go the other way, and perform DELETE on the resource at /students/:student_id/majors/:id
and well now UnderwaterBasketweaving is now no longer offered at this school...Whoops!
Now granted, we could set the destroy method of ClubsController, MajorsController, or StudentsController to look for club_id, or major_id, or student_id, but lets say we also down the road want to add Fraternities and GraduatingClasses, etc. Each class would start to be comprised of huge switch conditionals looking to see what param was present... and then find the collection of either the top resource and remove the bottom resource, or vise versa. The Models themselves should decide whether they delete themselves if they have no more association records... 'Destroy' on that resource has become really a misnomer...
Is there an easier way to do this? Even popular restful rails plugins like make_resourceful
or resource_controller
would blow away UnderwaterBasketweaving when removing it from Joe's Majors or completely delete JohnDoe when removing him from the major UnderwaterBasketweaving. It would seem there's a potential for looking at the association to understand the desired effects of the semantics and what 'destroy' should do.
Then again, am I looking at this all wrong? Is it not UnderwaterBasketweaving -> Joe but UnderwaterBasketweaving+Joe as a single resource and what we're deleting is truly not Joe, nor UnderwaterBasketweaving, but the resource representing the combination? However, that's not easy when the controllers are Students and Majors, that in effect represent resources of the same name (MVC has really become RV...in the 'convention' approach and not developing Controllers that may have no bearing on a Model name, or the path to reach it) So you'd be deleting a Major or a Student; pick your poison...
How can I avoid managing conditionals across an infinite graph of associated resources where delete really isn't the intent when the delete is desired to be in context of a collection and not pertaining to its singularity...?
...major.student.delete
... Is there a way for 'student' ActiveRecord object to know it was sent a 'delete' message in a method chain beginning with the 'major' AR object ?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
标准的 RESTful 方法是使用
has_many :through
并为关联资源生成一个控制器。命名关联资源总是很困难,但我会尝试这个例子。模型当然是:
等等(如果你想让我详细说明,请评论)
然后对于学生来说,你不会删除它关联的
@student.major
,而是他的@student.studies。其中:主要 => @主要
。Well the standard RESTful aproach is to use
has_many :through
and generate a cotroller for the association resource. Naming association resources is always difficult, but I'll attempt for this example.The models would be of course:
etc. (comment if you want me to elaborate)
Then for a student you wouldn't DELETE it's associated
@student.major
but his@student.studies.where :major => @major
.