【问题标题】:How to assign a has_many/belongs_to relation properly in Rails ActiveRecord?如何在 Rails ActiveRecord 中正确分配 has_many/belongs_to 关系?
【发布时间】:2012-11-30 16:52:59
【问题描述】:

我有一个带有文章和作者模型的 Rails 应用程序。如果我有作者和帖子,并且想表明作者应该是文章的所有者,或者文章属于作者,那么这样做的最佳做法是什么?特别是:

如果我设置它会有所不同

my_article.author_id = author_one.id

或者如果我这样做了

author_one << my_article

使用的关联是

  • 作者有_many文章
  • 文章归属于作者

顺便问一下,如果出现类似问题,最好的查找方法是什么?

【问题讨论】:

  • 您的关联设置正确,但是从 Rails 为此类内容提供了一个明确定义的模式的意义上来说,这两个代码示例都不是“正确的”。我建议你看一个教程(RailsCasts 很棒)——有很多博客示例可以帮助你理解。
  • @MrYoshiji 我想了解更多关于鲁迪提出的这个告诉-不要问的话题

标签: ruby-on-rails ruby activerecord


【解决方案1】:

以下3个没有区别:

my_article.author_id = author_one.id
my_article.save
# same as
my_article.author = author_one
my_article.save
# same as
author_one.articles << my_article

要设置特定帖子的所有者,最常见和可读的方法是:

post.author = author
post.save

更短的版本

post.update_attributes(author_id: author.id) # call an implicit save

【讨论】:

  • 提醒像我这样忘记的人:你不能使用像Post.update_all(author: Author.first)这样的东西,你需要这样做:Post.update_all(author_id: Author.first.id)由于:apidock.com/rails/ActiveRecord/Relation/update_all“它不会实例化涉及的模型它不会触发 Active Record 回调或验证”(也许这适用于 rails 6?)
【解决方案2】:

我假设您的意思是 author_one.articles &lt;&lt; my_article 而不仅仅是 author_one &lt;&lt; my_article

两者之间的一个区别是

author_one.articles << my_article

将立即将更改保存到数据库。即,如果之前没有保存过my_article,它将为my_article创建记录,或者将现有记录更新为author_id = author_one.id

my_article.author = author_one

my_article.author_id = author_one.id

在您执行 my_article.save 之前不会持久化

【讨论】:

    【解决方案3】:

    最好的办法是使用:

    has_and_belongs_to_many
    

    因为作者可能写过很多文章,而文章可以有很多作者。

    【讨论】:

      【解决方案4】:

      恕我直言,正确的做法是在您的 Article 类上创建一个实例方法,如下所示:

      class Author < ActiveRecord::Base
        ...
        def add_an_article(article)
          unless self.articles.include?(article)
            self.articles << article
          end
        end
      
      end
      

      这将为您的模型提供更好的语义并封装关联操作的逻辑...

      这样,您的班级也将符合告诉-不问原则: http://pragprog.com/articles/tell-dont-ask.

      不幸的是,大多数 Rails 社区都忽略了良好的 OO 原则,而更喜欢最简单但不正确的做事方式!

      【讨论】:

      • 我不是反对者,但实际上并不需要添加这样的方法。 Rails 提供了执行此操作的标准习惯用法。此外,当向文章添加作者时,需要保存的是文章(带有外键)而不是作者,但使用 &lt;&lt; 时会自动完成
      • 你对'
      • @Rudy 为什么add_an_article(article) 方法比方法articles &lt;&lt; (my_article) 更符合告诉-不问-原则?您是在谈论不添加两次文章的断言吗?如果我想防止这些东西被添加两次,为什么我不应该调整相关模型的articles &lt;&lt; 方法本身而不是添加一个新方法?
      • @Yo,我说的是对你不能做的事情做出假设。 1-存在 [code]
      • 在这种情况下,重复是这些不变量之一。但是想象一下(相信我,这并不罕见!)你有一个作者的所有文章都必须以字母“A”开头的情况?好吧,这个例子不是很好,但希望你明白......
      猜你喜欢
      • 1970-01-01
      • 2014-10-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-09-26
      相关资源
      最近更新 更多