【问题标题】:Rails API: One Request, Multiple Controller ActionsRails API:一个请求,多个控制器操作
【发布时间】:2018-04-18 01:21:35
【问题描述】:

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

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

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

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

有人使用过这两种方法吗?还有更好的方法吗?

谢谢, 尼古拉斯

【问题讨论】:

    标签: ruby-on-rails ruby


    【解决方案1】:

    我会在模型中通过一个请求来处理这个问题。如果您在ArticleAuthor 之间有has_many 关系,您可以在Article 模型上使用accept_nested_attributes_for。然后您可以在一个请求中传递Authorship 属性和Article 属性。

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

    model/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

    这是一个关于accepts_nested_attributes_for 的好blog post。你可以在official Rails documentation阅读它。

    我建议利用嵌套属性和 Rails 提供的关联方法,通过一个控制器操作中的一个 Web 请求来处理这一点。

    【讨论】:

    • 您的article.rb 的第一行看起来有点歪斜。也许你的意思是class Article &lt; ActiveRecord::Base
    【解决方案2】:

    通常您想要做这样的事情——在对象创建时创建关联记录——所有这些都在同一个事务中。如果在 Article 创建时自动创建 Authorship,我绝对不会考虑拆分 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 回调将这种关联对象创建卸载到模型中,这也是事务性的。但上面的成语似乎更典型。

    【讨论】:

    • 好的,所以在文章控制器中构建它。这就说得通了。谢谢!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-06-02
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多