第一个has_many是多余的吗? - Ruby on Rails活动记录关联

时间:2016-02-05 19:19:41

标签: ruby-on-rails postgresql activerecord ruby-on-rails-4.2

Rails 4.2新手:

2个问题;

1)第一个has_many是多余的吗?由于它的名字是Save Class的复数?

我可以只有:

has_many   :savers, through: :saves, source: :saver

甚至更好;

has_many   :savers, through: :saves

如果答案是肯定的,我可以在哪里设置"依赖:: destroy"?

class Post < ActiveRecord::Base
  belongs_to :user
  has_many   :saves, class_name: "Save", foreign_key: "saver_id", dependent: :destroy                        
  has_many   :savers, through: :saves, source: :saver
end

class Save < ActiveRecord::Base
  belongs_to :saver, class_name: "User"
  validates :saver_id, presence: true
end


class User < ActiveRecord::Base
  has_many :posts, dependent: :destroy
  ...
end

2)这是典型的博客模式,用户可以在其中保存&#39;由其他用户发布到他们的时间线的帖子。此模型是否使用最佳实践?特别是在db性能中,执行Join以获取用户保存的帖子。 &#39; Save&#39;将有100MM行的表?

2 个答案:

答案 0 :(得分:1)

让我们首先改变你的例子,使命名更容易混淆:

@user.posts

让我们看看执行irb(main):009:0> @user.posts Post Load (0.2ms) SELECT "posts".* FROM "posts" INNER JOIN "bookmarks" ON "posts"."id" = "bookmarks"."post_id" WHERE "bookmarks"."user_id" = ? [["user_id", 1]] => #<ActiveRecord::Associations::CollectionProxy []>

时生成的查询
has_many :bookmarks

现在让我们注释掉class User # has_many :bookmarks has_many :posts, through: :bookmarks end 并重新加载:

irb(main):005:0> @user.posts
ActiveRecord::HasManyThroughAssociationNotFoundError: Could not find the association :bookmarks in model User
has_many

所以不,第一个has_many through:并非多余 - 实际上它是has_many :posts, through: :bookmarks工作原理的核心。您可以通过其他关系设置快捷方式。

:bookmarks class Post < ActiveRecord::Base has_many :saves, dependent: :destroy has_many :savers, through: :saves end class Save < ActiveRecord::Base belongs_to :saver, class_name: "User" belongs_to :post # A join table with only one relation is pretty worthless. validates :saver_id, presence: true end class User < ActiveRecord::Base has_many :posts has_many :saves, dependent: :destroy has_many :posts, through: :saves end 中的注释是我们正在加入的名称关系。不是包含连接的表。

要修复原始代码,您需要执行以下操作:

has_many :savers, through: :saves

请注意,您不需要一半的垃圾 - 如果您有saver ActiveRecord将自行查找关系dependent: destroy。此外,您只想在联接模型上使用with open('test.csv', 'w') as fp: a = csv.DictWriter(fp, delimiter=',', fieldnames=flat.keys()) a.writeheader() a.writerow(flat) - 而不是在帖子关系上,因为这会删除用户拥有的所有帖子&#34;已保存&#34; - 甚至是其他人写的那些!

答案 1 :(得分:0)

自学Rails,我想学习使用框架的专业方法,并遵循Rails指南的最佳实践。这并不容易,因为我通常会找到“正常工作”的答案

我会尝试回答自己,也许它可能对Rails Newbies有用:

使用has_many through,association,Rails首先通过查看<class>_id形式的外键来推断关联,其中<class>是类名的小写,在本例中; 'save_id'。

因此,如果我们有列名'save_id',我们将有以下简化模型:

class Post < ActiveRecord::Base
  belongs_to :user                      
  has_many   :saves, through: :saves
end

class Save < ActiveRecord::Base
  belongs_to :savers, class_name: "User"
  validates :save_id, presence: true
end


class User < ActiveRecord::Base
  has_many :posts, dependent: :destroy
  ...
end