[英]Rails API: One Request, Multiple Controller Actions
I have multiple models that in practice are created and deleted together. 我有多个在实践中一起创建和删除的模型。 Basically I have an Article model and an Authorship model.
基本上,我有一个Article模型和一个Authorship模型。 Authorships link the many to many relation between Users and Articles.
作者身份将用户与文章之间的多对多关系联系起来。 When an Article is created, the corresponding Authorships are also created.
创建文章时,还将创建相应的作者资格。 Right now, this is being achieved by POSTing multiple times.
目前,这是通过多次POST实现的。
However, say only part of my request works. 但是,仅说我的请求的一部分有效。 For instance, I'm on bad wifi and only the create article request makes it through.
例如,我的wifi不好,只有create article请求可以通过。 Then my data is in a malformed half created, half not state.
然后,我的数据处于错误创建的状态,一半处于未创建状态。
To solve this, I want to send all the data at once, then have Rails split up the data into the corresponding controllers. 为了解决这个问题,我想一次发送所有数据,然后让Rails将数据拆分为相应的控制器。 I've thought of a couple ways to do this.
我想到了几种方法来做到这一点。 The first way is having controllers handle each request in turn, sort of chaining them together.
第一种方法是让控制器依次处理每个请求,将它们链接在一起。 This would require the controllers to call the next one in the chain.
这将要求控制器调用链中的下一个。 However, this seems sorta rigid because if I decide to compose the controllers in a different way, I'll have to actually modify the controller code itself.
但是,这似乎有点僵化,因为如果我决定以其他方式构成控制器,则必须实际修改控制器代码本身。
The second way splits up the data first, then calls the controller actions with each bit of data. 第二种方法是先拆分数据,然后用数据的每一位调用控制器动作。 This way seems more clean to me, but it requires some logic either in the routing or in a layer independent of the controllers.
这种方式对我来说似乎更干净,但是在路由或独立于控制器的层中都需要一些逻辑。 I'm not really clear where this logic should go (another controller? Router? Middleware?)
我不清楚这个逻辑应该去哪里(另一个控制器?路由器?中间件?)
Has anybody had experience with either method? 有没有人有使用任何一种方法的经验? Is there an even better way?
有没有更好的办法?
Thanks, Nicholas 谢谢尼古拉斯
Typically you want to do stuff like this -- creating associated records on object creation -- all in the same transaction. 通常,您想要做这样的事情-在对象创建时创建关联记录-全部都在同一事务中进行。 I would definitely not consider breaking up the creation of an
Authorship
and Article
if creating an Authorship
is automatic on Article
creation. 我绝对不会考虑分手的创建
Authorship
和Article
,如果创建一个Authorship
是自动上Article
创作。 You want a single request that takes in all needed parameters to create an Article
and its associated Authorship
, then you create both in the same transaction. 你想要的是发生在所有需要的参数,以创建单个请求
Article
及其相关Authorship
,那么你在同一个事务中创建两个。 One way would be to do something like this in the controller: 一种方法是在控制器中执行以下操作:
class Authorship
belongs_to :user
belongs_to :article
end
class Article
has_many :authorships
has_many :users, through: :authorships
end
class ArticlesController
def create
@article = Article.new({title: params[:title], stuff: [:stuff]...})
@article.authorships.build(article: @article, user_id: params[:user_id])
if @article.save
then do stuff...
end
end
end
This way when you hit @article.save
, the processing of both the Article
and the Authorship
are part of the same transaction. 这样,当您单击
@article.save
,对Article
和Authorship
都是同一事务的一部分。 So if something fails anywhere, then the whole thing fails, and you don't end up with stray/disparate/inconsistent data. 因此,如果某处发生任何故障,那么整个故障就会发生,并且您最终不会出现流浪/分散/不一致的数据。
If you want to assign multiple authorships on the endpoint (ie you take in multiple user id params) then the last bit could become something like: 如果要在终结点计算机上分配多个作者身份(即,使用多个用户ID参数),则最后一位可能类似于:
class ArticlesController
def create
@article = Article.new({title: params[:title], stuff: [:stuff]...})
params[:user_ids].each do |id|
@article.authorships.build(article: @article, user_id: id)
end
if @article.save
then do stuff...
end
end
end
You can also offload this kind of associated object creation into the model via a virtual attribute and a before_save
or before_create
callback, which would also be transactional. 您还可以通过虚拟属性和
before_save
或before_create
回调将这种关联的对象创建卸载到模型中,这也将是事务性的。 But the above idiom seems more typical. 但是以上习语似乎更典型。
I would handle this in the model with one request. 我将在模型中处理一个请求。 If you have a
has_many
relationship between Article
and Author
, you may be able to use accept_nested_attributes_for
on your Article
model. 如果
Article
和Author
之间具有has_many
关系,则可以在Article
模型上使用accept_nested_attributes_for
。 Then you can pass Authorship
attributes along with your Article
attributes in one request. 然后,您可以在一个请求中传递
Authorship
属性以及Article
属性。
I have not seen your code, but you can do something like this: 我没有看到您的代码,但是您可以执行以下操作:
model/article.rb 型号/article.rb
class Article < ActiveRecord::Base
has_many :authors, through: :authorship # you may also need a class_name: param
accepts_nested_attributes_for: :authors
end
You can then pass Author
attributes to the Article
model and Rails will create/update the Authors
as required. 然后,您可以将
Author
属性传递给Article
模型,Rails将根据需要创建/更新Authors
。
Here is a good blog post on accepts_nested_attributes_for. 这是有关accepts_nested_attributes_for的不错的博客文章 。 You can read about it in the official Rails documentation .
您可以在Rails官方文档中阅读有关它的信息 。
I would recommend taking advantage of nested attributes and the association methods Rails gives you to handle of this with one web request inside one controller action. 我建议您利用嵌套属性和关联方法,Rails通过一个控制器操作中的一个Web请求来处理此问题。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.