Rails API:一个请求,多个控制器操作

时间:2017-11-05 22:47:16

标签: ruby-on-rails ruby

我有多个模型在实践中一起创建和删除。 基本上我有一个文章模型和一个作者模型。作者关系链接用户和文章之间的多对多关系。创建文章时,还会创建相应的作者身份。现在,这是通过POSTing多次实现的。

但是,请说只有我的部分要求有效。例如,我的wifi很糟糕,只有创建文章请求才能通过。然后我的数据处于格式错误的一半创建,一半不是状态。

要解决这个问题,我想一次发送所有数据,然后让Rails将数据拆分成相应的控制器。我想过几种方法可以做到这一点。第一种方法是让控制器依次处理每个请求,将它们链接在一起。这将要求控制器调用链中的下一个控制器。然而,这看起来很严格,因为如果我决定以不同的方式组合控制器,我将不得不实际修改控制器代码本身。

第二种方法首先分割数据,然后用每一位数据调用控制器动作。这种方式对我来说似乎更干净,但它需要路由中的某些逻辑或独立于控制器的层。我真的不清楚这个逻辑应该去哪里(另一个控制器?路由器?中间件?)

有没有人有这两种方法的经验?还有更好的方法吗?

谢谢, 尼古拉斯

2 个答案:

答案 0 :(得分:3)

通常你想做这样的事情 - 在对象创建上创建相关记录 - 所有这些都在同一个事务中。如果在Authorship创建时自动创建Article,我绝对不会考虑放弃创建AuthorshipArticle。您希望单个请求接收所有必需参数以创建Article 其关联的Authorship,然后在同一事务中创建两者。一种方法是在控制器中做这样的事情:

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

这样,当您点击@article.save时,ArticleAuthorship的处理都是同一交易的一部分。因此,如果某些事情在任何地方都失败了,那么整个事情就会失败,并且你最终不会得到流浪/不同/不一致的数据。

如果你想在端点上分配多个作者身份(即你接受多个用户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

您还可以通过虚拟属性和before_savebefore_create回调将此类关联对象创建卸载到模型中,这也是事务性的。但上述成语似乎更为典型。

答案 1 :(得分:2)

我会在一个请求的模型中处理这个问题。如果您在has_manyArticle之间存在Author关系,则可以在accept_nested_attributes_for模型上使用Article。然后,您可以在一个请求中传递Authorship个属性以及Article属性。

我没有看到你的代码,但你可以这样做:

<强>模型/ 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

然后,您可以将Author个属性传递给Article模型,Rails会根据需要创建/更新Authors

这是Accept_nested_attributes_for上的一个好blog post。您可以在official Rails documentation

中阅读相关内容

我建议利用嵌套属性和关联方法Rails让您在一个控制器操作中通过一个Web请求处理此问题。