我有以下示例模型结构:
class Category < ActiveRecord::Base
has_many :posts
scope :active, -> { where(active: true) }
end
class User < ActiveRecord::Base
has_many :posts
has_many :visible_posts, -> { joins(:category).merge(Category.active) }, class: Post
has_many :visible_posts_comments, through: :visible_posts, source: :comments
has_many :comments
end
class Post < ActiveRecord::Base
belongs_to :category
belongs_to :user
has_many :comments
end
class Comment < ActiveRecord::Base
belongs_to :post
belongs_to :user
end
现在User.first.visible_posts_comments
引发了以下错误:
ActiveRecord::StatementInvalid: PG::UndefinedTable: ERROR: missing FROM-clause entry for table "categories"
LINE 1: ..." = "posts"."id" WHERE "posts"."user_id" = $1 AND "categorie...
这是因为此关联执行的SQL如下:
2.1.2 :009 > u.visible_posts_comments.to_sql
=> "SELECT \"comments\".* FROM \"comments\" INNER JOIN \"posts\" ON \"comments\".\"post_id\" = \"posts\".\"id\" WHERE \"posts\".\"user_id\" = $1 AND \"categories\".\"active\" = 't'"
visible_posts
在INNER JOIN
上添加categories
后,2.1.2 :010 > u.visible_posts.to_sql
=> "SELECT \"posts\".* FROM \"posts\" INNER JOIN \"categories\" ON \"categories\".\"id\" = \"posts\".\"category_id\" WHERE \"posts\".\"user_id\" = $1 AND \"categories\".\"active\" = 't'"
正常工作,
visible_posts_comments
为什么joins(:category)
似乎“丢失”merge(Category.active)
语句但保留through
?我认为没有理由故意放弃{{1}} - 联盟的联接。这是一个错误还是一个功能?
我使用的是activerecord-4.1.8。
答案 0 :(得分:3)
我创建了与您相同的rails项目,发现了同样的问题。 关于这个问题有两点:
#lib/active_record/associations/through_association.rb line 14
def target_scope
scope = super
chain.drop(1).each do |reflection|
relation = reflection.klass.all
relation.merge!(reflection.scope) if reflection.scope
scope.merge!(
relation.except(:select, :create_with, :includes, :preload, :joins, :eager_load)
)
end
scope
end
我认为他们这样做的原因是记录创建操作的考虑因素。恩。也许u.visible_posts_comments.create(...)会使ActiveRecord感到困惑
class Category < ActiveRecord::Base
has_many :posts
end
class User < ActiveRecord::Base
has_many :posts
has_many :visible_posts, -> { merge(Post.active) }, class: Post
has_many :visible_posts_comments, -> { joins(:post).merge(Post.active) }, class: Comment
has_many :comments
end
class Post < ActiveRecord::Base
belongs_to :category
belongs_to :user
has_many :comments
scope :active, -> { joins(:category).merge(Category.active) }
end
class Comment < ActiveRecord::Base
belongs_to :post
belongs_to :user
end