我试图围绕解决基于REST的API中的概念的最佳方式.不包含其他资源的平面资源没有问题.我遇到麻烦的地方是复杂的资源.
例如,我有一本漫画书的资源.ComicBook上有如各种属性author,issue number,date,等.
漫画书也有一份1..n封面清单.这些封面是复杂的对象.它们包含大量关于封面的信息:艺术家,日期,甚至是封面的64位编码图像.
对于GET上ComicBook我可以回相声,和所有的封面,包括他们的base64'ed图像.获得一部漫画可能不是什么大不了的事.但是假设我正在构建一个客户端应用程序,希望在表格中列出系统中的所有漫画.
该表将包含ComicBook资源中的一些属性,但我们当然不希望显示表中的所有封面.返回1000本漫画书,每本漫画书都有多个封面,这将导致大量数据流过网络,在这种情况下,最终用户不需要这些数据.
我的直觉是制作Cover资源并ComicBook包含封面.所以现在Cover是一个URI.GET漫画书现在可以使用,而不是Cover我们为每个封面发回一个URI 的巨大资源,客户可以根据需要检索封面资源.
现在我在创建新漫画方面遇到了问题.当我创建一个时,我肯定想要创建至少一个封面Comic,事实上这可能是一个商业规则.
所以现在我卡住了,我要么强制客户端通过先提交给执行业务规则Cover,获得URI为盖,然后POST荷兰国际集团一个ComicBook与URI列表,或者我POST就ComicBook需要在寻找不同的资源比它吐出出.传入的资源是POST和GET深拷贝,其中传出的GETs包含对依赖资源的引用.
Cover在任何情况下,资源可能都是必要的,因为我确信作为客户,我想在某些情况下解决覆盖方向问题.因此,无论依赖资源的大小如何,问题都以一般形式存在.一般来说,如何处理复杂的资源而不强迫客户只是"知道"这些资源是如何组成的?
我有一个关于form_for和嵌套资源的两部分问题.假设我正在编写一个博客引擎,我想将评论与文章联系起来.我已经定义了一个嵌套资源,如下所示:
map.resources :articles do |articles|
articles.resources :comments
end
Run Code Online (Sandbox Code Playgroud)
评论表单位于文章的show.html.erb视图中,位于文章本身下方,例如:
<%= render :partial => "articles/article" %>
<% form_for([ :article, @comment]) do |f| %>
<%= f.text_area :text %>
<%= submit_tag "Submit" %>
<% end %>
Run Code Online (Sandbox Code Playgroud)
这给出了一个错误,"为nil调用id,这会错误等等".我也试过了
<% form_for @article, @comment do |f| %>
Run Code Online (Sandbox Code Playgroud)
哪个呈现正确但将f.text_area与文章的"文本"字段而不是注释相关联,并在该文本区域中显示了article.text属性的html.所以我似乎也有这个错误.我想要的是一个表单,其'submit'将在CommentsController上调用create action,在params中有一个article_id,例如对/ articles/1/comments的post请求.
我的问题的第二部分是,开始创建评论实例的最佳方法是什么?我正在ArticlesController的show动作中创建一个@comment,因此一个注释对象将在form_for帮助器的范围内.然后在CommentsController的create动作中,我使用从form_for传入的参数创建新的@comment.
谢谢!
我正在为一个兔子农民建立一个网站(让我们假装).这个男人密切关注他的兔子,并希望他们都归类.所以我为他建了一个RabbitCategoriesController,并将这一行添加到我的routes.rb中
resources :rabbit_categories
Run Code Online (Sandbox Code Playgroud)
的URL被作为表示向上rabbit_categories,rabbit_categoriew/new等
如果我希望网址看起来像rabits/categories rabits/categories/new怎么办?这不是嵌套资源,我只是想改变URL的外观.
当然,如果资源被称为"类别",我可以做到
namespace :rabbits do
resources :categories
end
Run Code Online (Sandbox Code Playgroud)
有什么办法我可以写,但告诉它使用RabbitCategoriesController而不是Rabbits :: CategoriesController?
正如我对嵌套资源的理解,边缘Rails,不应该
link_to 'User posts', @user.posts
Run Code Online (Sandbox Code Playgroud)
指向
/users/:id/posts
Run Code Online (Sandbox Code Playgroud)
?
routes.rb文件包含
map.resources :users, :has_many => :posts
Run Code Online (Sandbox Code Playgroud)
如果这不是默认行为,可以通过其他方式完成吗?
我有一个简单的用户模型,带有一个单一的嵌套Profile资源,因此在我的routes.rb中我有:
resources :users do
resource :profile, :only => [:edit, :update, :show]
end
Run Code Online (Sandbox Code Playgroud)
这会生成预期的路线:
edit_user_profile GET /users/:user_id/profile/edit(.:format) {:action=>"edit", :controller=>"profiles"}
user_profile GET /users/:user_id/profile(.:format) {:action=>"show", :controller=>"profiles"}
user_profile PUT /users/:user_id/profile(.:format) {:action=>"update", :controller=>"profiles"}
Run Code Online (Sandbox Code Playgroud)
我创建了一个简单的控制器更新方法来更新模型,然后在成功更新时重定向:
def update
@profile = Profile.find_by_user_id(params[:user_id])
@user = User.find_by_id(params[:user_id])
respond_to do |format|
if @profile.update_attributes(params[:profile])
format.html { redirect_to( user_profile_path(@user, @profile), :notice => 'Profile was successfully updated.') }
else
# ...
end
end
end
Run Code Online (Sandbox Code Playgroud)
问题是,一旦提交表单,表单就会重定向到mydomain.com/users/4/profile.22,其中22恰好是配置文件的ID.显然,这会使控制器混淆,因为路由将'22'解释为格式.
我的问题是,如何将其重定向到mydomain.com/users/4/profile呢? 我已经在redirect_to语句中尝试了以下变体而没有效果,它们都会导致相同的错误网址:
redirect_to( user_profile_path(@user), ... )
redirect_to( user_profile_path(@user, @profile), ... )
redirect_to([@user, @profile], ... )
redirect_to( @profile, ... …Run Code Online (Sandbox Code Playgroud) 假设我的应用程序有两个型号,Foo和Bar.
Foo可选择belongs_to Bar.
现在我可以查看单个Foo,或者搜索特定的Foo,而FoosController可以处理所有这些.我的URL就像:
foos/1和foos/new
有时我想看一个酒吧.BarsController处理它,我得到它:
bars/1或bars/1/edit.
如果我正在看一个酒吧,我可能想浏览那个酒吧的所有Foos.所以,我想bars/1/foos/看看那些Foos.
嵌套资源非常简单,它看起来像这样:
resources :foo
resources :bar do
resources :foo
end
Run Code Online (Sandbox Code Playgroud)
然而,作为酒吧的一部分的Foos有点特别,与常规的Foos不同.所以,例如,如果我加载foos/1或者bars/1/foos/1,我会看同样的Foo,但我在每种情况下都专注于不同的信息.
因此,我一直在考虑使用BarFoos控制器来处理Foos,因为它们处于Bar的环境中.但是,如果我将BarFoos嵌入Bar下,那么我的助手将会像bar_bar_foos_path和new_bar_bar_foo_path.这似乎是多余的.
所以,现在我正在考虑命名空间,这是我以前从未研究过的东西.我在rails指南中看到我可以定义:
namespace "bar" do
resources :foos
end
Run Code Online (Sandbox Code Playgroud)
如果我这样做,我可以在第二FoosController下app/bar/,并且FoosController可以处理一个酒吧里面的Foos与好的帮助,bar_foo_path(:id)而不是bar_bar_foo_path(:id).
但如果我这样做,我BarsController会怎么样?请求如何被路由到BarsController而不是resources :bars我有namespace "bar"?
最后,在我的辅助FoosController中我需要做些什么特别的工作来确保与顶级FoosController没有名称冲突?我意识到路由说"命名空间",但其余的ruby代码如何知道app/bar/foos_controller并且app/foos_controller不是同一个类?
谢谢!
routes namespaces ruby-on-rails nested-resources ruby-on-rails-3
我有一个属于许多不同模型的嵌套资源.例如:
resources :users do
resources :histories, only: [:show]
end
resources :publications do
resources :histories, only: [:show]
end
resources :events do
resources :histories, only: [:show]
end
Run Code Online (Sandbox Code Playgroud)
在HistoriesController,我想找到父对象,虽然我很难想到一个干燥的方法来处理这个问题.目前,我能想到的最好的是:
if params[:user_id].present?
@parent = User.find(params[:user_id])
elsif params[:publication_id].present?
@parent = Publication.find(params[:publication_id])
elsif . . . .
Run Code Online (Sandbox Code Playgroud)
我有几十个模型,我必须以这种方式分支,这似乎很草率.我不考虑更好的(可能是烘焙的)方法吗?
我希望用嵌套资源实现我的新API.
Example: /api/users/:user_id/posts/
Run Code Online (Sandbox Code Playgroud)
将评估特定用户的所有帖子.我还没有看到这个用例的工作示例,也许这不是实现rest API的正确方法?
我的问题是在为API目的构建URL时嵌套资源的优势.考虑以下两种用于访问员工资源的备选方案:
/api/employees?department=1 # flat
Vs.
/api/departments/1/employees # nested
Run Code Online (Sandbox Code Playgroud)
现在考虑开发通用库以从API访问REST资源的任务.如果所有路由都是平坦的,那么这样的REST包装器库只需要知道被访问资源的名称:
store.query('employees', {department_id:1}) => /api/employees?department=1
Run Code Online (Sandbox Code Playgroud)
但是,如果我们要支持嵌套路由,那么这个包装器需要知道有关嵌套模型和其他资源的额外信息,以便了解如何构建用于引用此类模型的URL.鉴于并非所有模型都嵌套在相同的父资源下,甚至一些模型根本不会嵌套,REST包装器库需要具有某种配置来描述所有这些额外的知识,否则这些知识是不需要的.
所以我的问题是:
API中的嵌套资源路由是否有任何实际优势?(这并不意味着最终用户使用,因此拥有更漂亮的URL可以获得更少的收益).
嵌套方法是否真的比平面更好,超越美学,以便证明为支持资源URL构建缺乏统一性而引入的额外努力和复杂性?
另见:https://stackoverflow.com/a/36410780/621809
更新:重要的澄清
我从一些评论和答案中了解到,我对一个方面不够清楚:我并不反对使用/employees/5或等URL来处理单个资源/departments/1.我不认为这是嵌套的.
当我说嵌套资源时,我指的是像/departments/1/employees资源一直在另一个资源的上下文中寻址的URL .主要问题是,对于URL构建,通用库需要知道额外的东西,如"员工嵌套在部门下",但"分支不嵌套在任何东西下".如果所有资源都可以通过REST来解决,但是以平面方式解决,知道如何解决它们会更简单,更容易预测.
当您考虑它时,在数据库中,您不需要知道额外的信息,以便知道如何处理对象集合(例如RDMS中的表).您总是将员工集合称为employees,而不是departments/5/employees.
我有一类称为Imprintables嵌套资源Styles,Brands,Colors,和Sizes.我目前在我的路线文件中有这个:
resources :imprintables do
resources :styles, :brands, :colors
resources :sizes do
collection do
post 'update_size_order'
end
end
end
Run Code Online (Sandbox Code Playgroud)
哪个产生这样的路线:
/imprintables/:imprintable_id/brands
/imprintables/:imprintable_id/colors
/imprintables/:imprintable_id/styles
/imprintables/:impritnable_id/sizes
Run Code Online (Sandbox Code Playgroud)
我不希望所有嵌套资源都绑定到1个特定的imprintable.我希望我的路线看起来像:
/imprintables/brands
/imprintables/styles
/imprintables/colors
/imprintables/sizes
Run Code Online (Sandbox Code Playgroud)
...等等.
什么是最好的方式来解决这个问题?
nested-resources ×10
rest ×3
routes ×2
api ×1
api-design ×1
django ×1
form-for ×1
namespaces ×1
python ×1
resources ×1
restful-url ×1
routing ×1
ruby ×1
url-routing ×1